The reason for this occurrence lies in the concept of excess property checking, which specifically applies to properties within object literals under certain conditions. Excess properties are not a significant type safety concern; the compiler only alerts about them if it anticipates that they may be disregarded immediately. For example, defining
const x: {a: string} = {a: "", b: ""}
is problematic because the
b
property cannot be safely accessed. On the other hand, assigning
const y = {a: "", b: ""}; const x: {a: string} = y;
is acceptable as
y
retains the information about
b</code even if <code>x
does not.
In general, having extra properties is not an issue related to type safety. It is necessary for the compiler to permit these additional properties for interface extension compatibility. TypeScript's structural type system would be compromised without this flexibility. While TypeScript lacks "exact types" like Flow, there is an ongoing request for their implementation at microsoft/TypeScript#12936. Currently, TypeScript relies on structural subtyping where {a: string, b: string}
can be assigned to {a: string}
, along with excess property checking that issues warnings selectively in specific scenarios.
When initializing bar
, you're spreading foo
, an existing variable, thus bypassing excess property checking since it's not an object literal. This behavior aligns with the intention outlined in ms/TS#41237.
Conversely, the initialization of qux
involves adding excess properties directly within an object literal, triggering a warning because there's no mechanism in place to remember that qux
includes a prop2
property.