keyof Foo 与 Object.keys(Foo)

keyof Foo vs Object.keys(Foo)

谁能解释为什么会这样:

let foo = new Foo(),
    x: (keyof Foo)[] = Object.keys(foo)

导致:

Type 'string[]' is not assignable to type '"bar" | "bar1"...'

(使用 tsc 2.1.4)

方法Object.keys(...)returns一个字符串数组:

class Foo {
    public foo: string;
    public bar: string;
}

let foo = new Foo(),
    x: string[] = Object.keys(foo)

TypeScript 不会完全评估 Object.keys 的结果,以保证值是正确的...尽管您可以看到它们在此示例中是兼容的... .

type example = keyof Foo; // "foo", "bar"

所以您的类型注释在您的原始示例中是正确的,但是 TypeScript 没有为 Object.keys 结果提供这样的特定类型。

我认为这是因为 keyof 运算符在类型声明 space 中运行,而 Object.keys returns 你是来自变量声明的变量 space。而且您不能简单地将不同 space 的值相互分配。

有关此事的更多信息:spaces

你可以输入断言,然后就可以了:

class Foo {
    x: number;
    y: number;
}

type Keys = keyof Foo;

let foo = new Foo(),
    x = Object.keys(foo) as Keys[];

(code in playground)

问题是您试图将 string[] 放入(在我的示例中)更具体的 ('x' | 'y')[]
这里也会发生同样的情况:

interface A {
    x: number;
}

interface B extends A {
    y: number;
}

let a: A = { x: 5 };
let b1: B = a; // error
let b2: B = a as B; // fine

当您想将某些内容转换为更具体的类型时,您需要通过类型断言告诉编译器您知道自己在做什么。