如果接口是兼容的(即它们没有任何不兼容类型的属性),Typescript 将允许您在联合类型中指定任何属性。我们可以定义一个类型,确保对象字面量只与其中一个接口兼容,方法是向联合类型的每个类型添加来自其他类型的所有属性,并使用 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>