推断字符串的关键字 当key只是一个字符串时的数字

don*_*don 18 typescript typescript-typings

我这样定义AbstractModel:

export interface AbstractModel {
   [key: string]: any
}
Run Code Online (Sandbox Code Playgroud)

然后我宣布类型Keys:

export type Keys = keyof AbstractModel;
Run Code Online (Sandbox Code Playgroud)

我希望任何具有Keys类型的东西都可以单义地解释为字符串,例如:

const test: Keys;
test.toLowercase(); // Error: Property 'toLowerCase' does not exist on type 'string | number'. Property 'toLowerCase' does not exist on type 'number'.
Run Code Online (Sandbox Code Playgroud)

这是一个Typescript(2.9.2)的错误,还是我错过了什么?

jma*_*eis 24

如TypeScript 2.9的发行说明中所定义,如果您使用字符串索引签名键入接口,则返回字符串和数字的并集

给定对象类型X,keyof X解析如下:

如果X包含字符串索引签名,则keyof X是字符串,数字和表示符号类属性的文字类型的并集,否则

如果X包含数字索引签名,则keyof X是数字和文字类型的并集,表示类似字符串和符号的属性,否则

keyof X是表示类似字符串,类似数字和类似符号的属性的文字类型的并集.

资源

这是因为:JavaScript在索引对象时将数字转换为字符串:

[...]在使用数字进行索引时,JavaScript实际上会在索引到对象之前将其转换为字符串.这意味着使用100(数字)索引与使用"100"(字符串)进行索引相同,因此两者需要保持一致.

资源

例:

let abc: AbstractModel = {
    1: "one",
};

console.log(abc[1] === abc["1"]); // true
Run Code Online (Sandbox Code Playgroud)

当您只需要字符串键时,您只能从界面中提取字符串键,如下所示:

type StringKeys = Extract<keyof AbstractModel, string>;

const test: StringKeys;
test.toLowerCase(); // no error
Run Code Online (Sandbox Code Playgroud)

此外,TypeScript编译器提供了一个选项来获取前2.9的行为keyof:

keyofStringsOnly(boolean)默认值 false

仅解析keyof为字符串值属性名称(无数字或符号).

资源

  • @Aure77尝试删除`string`周围的双引号 (2认同)

mad*_*ox2 5

我也遇到过类似的问题。我通过将key强制为字符串来解决它:

export type Keys = keyof AbstractModel & string;
Run Code Online (Sandbox Code Playgroud)

另一种选择是将密钥转换为字符串: test.toString().toLowercase()

  • 这和“Extract&lt;keyof AbstractModel, string&gt;”之间有任何实际差异吗? (3认同)
  • 非常有用,是全局设置“keyofStringsOnly: true”选项的绝佳上下文替代方案。 (2认同)

Pie*_*Duc 5

对于通用打字稿实用程序,您可以使用以下内容:

type KeyOf<T extends object> = Extract<keyof T, string>;
Run Code Online (Sandbox Code Playgroud)

用法:

const sym = Symbol();

const obj = {
  [sym]: true,
  foo: 'foobar',
  bar: 'barfoo',
  1: 'lorem'
}

let key: KeyOf<typeof obj> = 'foo'; // 'foo' | 'bar'

key = 'bar'; // ok
key = 'fool'; // error
key = 1; // error
Run Code Online (Sandbox Code Playgroud)

操场