给出以下代码:
interface t1 {
prop1: string;
}
interface t2 {
prop2: string;
}
type ts = t1 | t2;
const t: ts = {
prop1: 'foo',
prop2: 'bar'
}
为什么t
对象有效?这可能是不允许的,因此t
只能是t1
或t2
,而不能同时为两者?
可以在打字稿操场here上看到代码。
答案 0 :(得分:3)
如果接口兼容(即它们不具有任何不兼容类型的属性),则Typescript将允许您指定union类型中的任何属性。我们可以定义一个类型,确保对象文字只与其中一个接口兼容,方法是向每个类型的union类型添加其他类型的所有属性,使用never类型:
type Diff<T extends string, U extends string> = ({[P in T]: P } & {[P in U]: never } & { [x: string]: never })[T];
type Exclude<T, TExclude> = Partial<Record<Diff<keyof TExclude, keyof T>, never>>
type ts = (t1 & Exclude<t1,t2>) | (t2 & Exclude<t2, t1>);
interface t1 {
prop1: string;
prop4: string;
propCommon: string;
}
interface t2 {
prop2: string;
propCommon: string;
}
const t: ts = { prop1: 'foo',prop2: 'bar', propCommon: ''}
const tt2: ts = {prop2: '', propCommon: ''}
const tt1: ts = {prop1: '', propCommon: '', prop4: ''}
对于3种类型,用法是:
type ts = (t1 & Exclude<t1,t2> & Exclude<t1, t3>)
| (t2 & Exclude<t2, t1> & Exclude<t1, t3>)
| (t3 & Exclude<t3, t1> & Exclude<t3, t2>);
我们还可以定义一些辅助类型,使其看起来更好一些:
type Exclusive2<T, TExclude> = T & Exclude<T,TExclude>
type Exclusive3<T, TExclude, TExclude2> = T & Exclude<T,TExclude> & Exclude<T,TExclude2>
type Exclusive4<T, TExclude, TExclude2, TExclude3> = T & Exclude<T,TExclude> & Exclude<T,TExclude2> & Exclude<T, TExclude3>
type ts = Exclusive3<t1, t2, t3> | Exclusive3<t2, t1, t3> | Exclusive3<t3, t2, t1>