Reputation: 537
Can anyone explain why this:
let foo = new Foo(),
x: (keyof Foo)[] = Object.keys(foo)
leads to:
Type 'string[]' is not assignable to type '"bar" | "bar1"...'
(Using tsc 2.1.4)
Upvotes: 1
Views: 1500
Reputation: 164139
You can type assert it and then it's fine:
class Foo {
x: number;
y: number;
}
type Keys = keyof Foo;
let foo = new Foo(),
x = Object.keys(foo) as Keys[];
The problem is that you are trying to put string[]
into (in my example) ('x' | 'y')[]
which is more specific.
The same will happen here:
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
When you want to turn something into a more specific type then you need to tell the compiler that you know what you're doing by type asserting it.
Upvotes: 2
Reputation: 250882
The method Object.keys(...)
returns an array of strings:
class Foo {
public foo: string;
public bar: string;
}
let foo = new Foo(),
x: string[] = Object.keys(foo)
TypeScript doesn't fully evaluate what the result of Object.keys
will be in order to guarantee the values will be the right ones... although you can see that they will be compatible in this example...
type example = keyof Foo; // "foo", "bar"
So your type annotation is correct in your original example, but TypeScript doesn't give such a specific type to the Object.keys
result.
Upvotes: 0
Reputation: 22352
I believe this is due to the fact that keyof
operator operates in type declaration space whereas Object.keys
returns you the variable that is from variable declaration space. And you cant simply assign values from different spaces to each other.
More on the matter: spaces
Upvotes: 2