使用 keyof 运算符时,extends 子句中的通用参数未正确缩小范围

问题描述 投票:0回答:3
typescript
3个回答
1
投票

定义

R extends { [key: string]: any }
不限制由数字或符号作为键的属性,因为这些都是JavaScript对象中可能的键类型,而不仅仅是那些与索引签名匹配的键类型。

例如以下代码类型正确:

type AType = {
    [key: string]: any;
}

const aConst: AType = {
    "aaa": 1,
    2: 2
}

要仅考虑字符串键,您可以使用附加条件类型声明:

type TypedRouter<P extends string> = any

type Test<R> = R extends {
  [key: string]: any;
}
  ? {
      [P in keyof R]: P extends string ? TypedRouter<P> : never // ensuring only string keys considered
    }
  : never;

1
投票

IIUC,您想要一个映射类型将(某物)的字典重新映射到 TypedRouter 的字典中,但后者需要一个

string
类型。

TypedRouter<P & string>
解决方法有效,但保留了不正确的键(基本上,它仍然重新映射它们,但
P & string
产生一个
never
类型,TypedRouter可能处理或不处理):

type TypedRouter<P extends string> = P extends never ? "never" : "ok"

const s1 = Symbol(1)
type T = Test<{
  // ^? { 0: "never"; [s1]: "never"; str: "ok"; }
  0: 0,
  [s1]: 1,
  str: 2
}>

如果您想在重新映射期间拒绝这些键,只需 产生一个

never
key:

您可以通过生成

never

来过滤掉键

您的情况:

type Test2<R> = R extends {
  [key: string]: any;
}
  ? {
    [P in keyof R & string]: TypedRouter<P>
  }
  : never;

type T2 = Test2<{
  // ^? { str: "ok"; }
  0: 0,
  [s1]: 1,
  str: 2
}>

游乐场链接


0
投票

这个怎么样?

type TypedRouter<P extends string> = { route: P };

type Test<R> = R extends { [key: string]: any }
  ? {
      [P in keyof R]: TypedRouter<P & string>;
    }
  : never;

// Example usage
type Example = {
  path1: string;
  path2: number;
  path3: boolean;
};

type Result = Test<Example>;

// Correct usage: Displaying type structure in a comment
// type Result should look like:
// {
//   path1: TypedRouter<"path1">;
//   path2: TypedRouter<"path2">;
//   path3: TypedRouter<"path3">;
// }

console.log("Type Result structured correctly.");
© www.soinside.com 2019 - 2024. All rights reserved.