I'm failing to understand why this piece of code works when using the Omit utility type:
type Foo = {
prop1: string;
prop2: string;
}
const foo: Foo = {
prop1: 'prop1',
prop2: 'prop2'
}
console.log(foo) // {"prop1": "prop1", "prop2": "prop2"}
type Bar = Omit<Foo, 'prop2'> & {
prop3: string;
}
const bar: Bar = {
...foo,
prop3: 'prop3'
}
console.log(bar) // {"prop1": "prop1", "prop2": "prop2", "prop3": "prop3"}
Meanwhile, using Bar directly fails as expected:
const qux: Bar = {
prop1: "prop1",
prop2: "prop2", // '{ prop1: string; prop2: string; prop3: string; }' is not assignable to type 'Bar'
prop3: "prop3"
}
This happens because excess property checking only happens on properties in object literals, and only in some circumstances. Excess properties are not really a type safety issue; the compiler only warns about them if it thinks the code is likely to immediately forget about them. Something like
const x: {a: string} = {a: "", b: ""}is a problem because nothing will be able to access thatbproperty safely. Butconst y = {a: "", b: ""}; const x: {a: string} = y;is fine becauseyremembersbeven ifxforgets it.Again, in general, extra properties are not a type safety issue. You want the compiler to allow extra properties, otherwise interface extension wouldn't work (if
interface Foo {a: string}andinterface Bar extends Foo {b: string}, then forbidding extra properties would mean thatBaris not compatible withFoo, and TypeScript's structural type system would be defeated). TypeScript doesn't really have "exact types" the way Flow does. There's an open request at microsoft/TypeScript#12936 to support exact types, but right now we don't have them. All we have is structural subtyping where{a: string, b: string}is assignable to{a: string}, and excess property checking which sometimes issues a warning about that, in very specific situations.In the initializer to
baryou are spreadingfoo, an already-existing variable. It's not an object literal, and therefore there is no excess property checking. This is working as intended as per ms/TS#41237.On the other hand, your initializer for
quxis adding excess properties directly in an object literal, which does issue a warning, because nothing will remember thatquxhas aprop2property.