Why does the following code compile successfully? Since bar
is not part of MyState
, I would expect it to generate a compiler error.
type MyState = { foo: number; };
type Reducer<T> = (state: T) => T;
const wtf: Reducer<MyState> = (state) => {
return { foo: 123, bar: 123 }; // `bar` isn't part of MyState
};
crashmstr's answer is correct but it's worth explaining why this case is different from one where you do get an error.
Object literals only cause extra property errors in specific cases.
In this case:
var x: MyState = { foo: 10, bar: 20 };
The type system does the following steps:
{foo: 10, bar: 20}
MyState
?
foo
property?
10
-> number
)The key thing here is freshness. A type from an object literal is fresh if it comes directly from the object literal itself. This means there's a difference between
// Error
var x: MyState = { foo: 10, bar: 20 };
and
// OK
var x1 = { foo: 10, bar: 20 };
var x2: MyState = x1;
because the freshness of the object literal vanished once it was assigned into x1
.
Your example suffers the same fate - the freshness of the object literal is gone once it became part of the function return type. This also explains why the error re-appears if you have a return type annotation on the function expression.
Type compatibility in TypeScript is based on structural subtyping. Structural typing is a way of relating types based solely on their members. This is in contrast with nominal typing.
Type Compatibility
To check whether y can be assigned to x, the compiler checks each property of x to find a corresponding compatible property in y. In this case, y must have a member called name that is a string. It does, so the assignment is allowed. Note that y has an extra location property, but this does not create an error. Only members of the target type (Named in this case) are considered when checking for compatibility.
So in your example, { foo: 123, bar: 123 }
meets the requirement of having a foo
that is a number, and the extra bar
is ignored for type compatibility.
Note: See also Why am I getting an error “Object literal may only specify known properties”?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With