Typescript: prevent assignment of object with more properties than is specified in target interface
Solution 1:
The other answers here are essentially correct: types in TypeScript are generally open/extendable and can always have properties added; that is, they are not exact types (as requested in microsoft/TypeScript#12936) in which only known properties are allowed to exist. TypeScript doesn't really support exact types in general, although it does treat the types of freshly created object literals as exact types via excess property checks, as you've noticed.
If you really want to forbid a particular property key from a type in TypeScript, you can do this by making the property optional and have its type be never
or undefined
:
interface IUserSansPassword {
username: string;
email: string;
password?: never; // cannot have a password
}
declare class UserSansPassword implements IUserSansPassword {
username: string;
email: string;
password?: never; // need to declare this also
}
Now UserSansPassword
is known not to have a defined password
property. Of course now the following is an error:
interface IUser extends IUserSansPassword { // error!
// Types of property "password" are incompatible
password: string;
}
You can't extend IUserSansPassword
by adding a password... if A extends B
then you can always use an A
instance where a B
instance is expected. What you can do is extend a related type, your original IUserSansPassword
, which can be computed using the Omit
helper type:
interface IUser extends Omit<IUserSansPassword, "password"> {
password: string;
}
declare class User implements IUser {
username: string;
email: string;
password: string;
}
And then the following is an error like you expect:
const userSansPassword: UserSansPassword = new User();
// error, mismatch on "password" prop
Okay, hope that helps; good luck!
Link to code