Typescript object types are flexible and extensible, rather than rigid and exact. This means that an object of a certain type can have more properties than what is explicitly defined for that type. Object type definitions only cover the known properties of a type, not all possible unknown properties.
This openness is crucial for interface extension and class inheritance. For example:
interface Payload {
id: number;
}
interface GreatPayload extends Payload {
surprise: 4;
}
Here, GreatPayload
inherits from Payload
with an additional property but is still considered to be a type of Payload
. The same concept applies to class inheritance as well.
The only scenario where Typescript treats object types as exact is when creating a new object literal and assigning it to a specific type. This behavior is documented in the "Excess Property Checks" section of the TypeScript Handbook. These checks prevent errors caused by misspelled optional properties or unexpected keys within object literals.
If you wish for exact types to be implemented in Typescript, you can show your support on the related GitHub issue (microsoft/TypeScript#12936). However, since this feature may not be added soon, it's best to work with open types rather than against them. Ensure your code can handle extra properties gracefully by iterating through known keys instead of relying on methods like Object.keys()
.
Adopting practices that make your code resistant to unknown properties will allow you to safely interact with objects that have more properties than anticipated. Good luck!
Playground link to code