Reputation: 4323
Simple code example:
type Foo = { foo: string };
type FooBar = { foo: string; bar: number };
let a: Foo;
// Doesn't work
a = { foo: 'x', bar: 1 };
/*
Type '{ foo: string; bar: number; }' is not assignable to type 'Foo'.
Object literal may only specify known properties, and 'bar' does not exist in type 'Foo'.
*/
// However this works: (temp variable with implicit type)
let b = { foo: 'x', bar: 1 }; // According to VSCode the inferred type for `b` is exactly `{ foo: string; bar: number; }`
a = b;
// This also works: (temp variable with explicit type)
let c: FooBar = { foo: 'x', bar: 1 };
a = c;
This is very surprising to me. What I'd expect is an error in all three cases. I really like this idea of "Object literal may only specify known properties".
#1 Why is this happening?
#2 How can I configure TypeScript to not allow this "workaround"?
Upvotes: 1
Views: 214
Reputation: 37958
This is not workaround, but how type compatibility defined in typescript:
The basic rule for TypeScript’s structural type system is that x is compatible with y if y has at least the same members as x
Now why first example (let a: Foo = { foo: 'x', bar: 1 }
) errors? This is called excess property checks:
Object literals get special treatment and undergo excess property checking when assigning them to other variables, or passing them as arguments. If an object literal has any properties that the “target type” doesn’t have, you’ll get an error
How can I configure TypeScript to not allow this "workaround"? This is not possible currently. You can find old discussion on exact types here, but I doubt it will make to typescript in near future.
Upvotes: 3