Consider the following case. There is no error reported by Typescript while calling func with argument of type One - why?
export interface One {
common?: string
one?: string;
}
export interface Two {
common?: string
two?: string;
}
export function func(arg: Two) {
// do something!
}
const one: One = {
common: 'common',
one: 'One'
};
const two: Two = {
common: 'common',
two: 'Two'
}
func(one);
The underlying issue is that One and Two are mutually compatible types as you have defined them.
I don't know if there's a more canonical source of documentation for this, but the (somewhat outdated) TypeScript specification says that all the properties of a target object type T are compatible with the analogous properties of a source type S, then a value of type S is assignable to variable of type T.
In your case, One is assignable to Two because:
Two's property common is an optional string value, and so is One's; andTwo's property two is an optional string value, and One doesn't have a property of this name.And Two is assignable to One for analogous reasons:
One's property common is an optional string value, and so is Two's; andOne's property one is an optional string value, and Two doesn't have a property of this name.This compatibility is possibly surprising. TypeScript 2.4 introduced weak type detection which will complain if you try to assign any value to an all-optional-property type like One or Two unless they share at least one property. This prevents some crazy stuff like {a?: string} being compatible with {b?: number}, but in your case the fact that common exists in both One or Two disables the weak type checking.
My suggestion here is that if you have two types which are accidentally compatible, you can distinguish them by explicitly adding the problematic property keys to the other types as optional properties of type never or undefined:
export interface One {
common?: string
one?: string;
two?: undefined;
}
export interface Two {
common?: string
one?: undefined;
two?: string;
}
This isn't much different in terms of what you intend to assign to these types:
const one: One = {
common: 'common',
one: 'One'
}; // still okay
const two: Two = {
common: 'common',
two: 'Two'
} // still okay
but now the compiler sees One and Two as incompatible as desired:
func(one); // error!
// ~~~ <-- Types of property 'one' are incompatible.
Okay, hope that helps; good luck!
Playground link to code
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