代码之家  ›  专栏  ›  技术社区  ›  don

当key仅为字符串时,Keyof推断字符串|数字

  •  6
  • don  · 技术社区  · 6 年前

    我定义了 AbstractModel 就像这样:

    export interface AbstractModel {
       [key: string]: any
    }
    

    然后我声明类型 Keys :

    export type Keys = keyof AbstractModel;
    

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

    这是Typescript(2.9.2)的错误,还是我遗漏了什么?

    2 回复  |  直到 6 年前
        1
  •  27
  •   jmattheis zzz    6 年前

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

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

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

    keyof X是表示类字符串、类数字和类符号属性的文本类型的并集。

    source

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

    [.]用数字索引时,JavaScript实际上会在索引到对象之前将其转换为字符串。这意味着用100(一个数字)索引与用“100”(字符串)进行索引是一样的,所以两者需要一致。

    source

    例子:

    let abc: AbstractModel = {
        1: "one",
    };
    
    console.log(abc[1] === abc["1"]); // true
    

    type StringKeys = Extract<keyof AbstractModel, string>;
    
    const test: StringKeys;
    test.toLowerCase(); // no error
    

    TypeScript编译器还提供了一个选项来获取 keyof :

    false

    决心 钥匙 仅字符串值属性名称(无数字或符号)。

    source

        2
  •  8
  •   madox2    6 年前

    我也遇到过类似的问题。我通过将key强制为string解决了这个问题:

    export type Keys = keyof AbstractModel & string;
    

    test.toString().toLowercase()