我有“成对出现”的键值对。换句话说,如果我有一个键值对A:B
,那么我也想要求我的对象具有C:D
,但是它也不能有一对。 (将message:string
用于一对,将min-length:number
用于另一对。)是否有一种优雅的方法来制作由任意数量的此类对组成的接口?
编辑: 为了澄清起见,我想为允许使用这些对象的对象设计一个接口:
{
//First pair
message1: string;
minLength1: number;
//Second pair
message2: string;
minLength2: number;
// ...
}
{
//First pair omitted altogether
//Just the second pair
message2: string;
minLength2: number;
}
...但是不允许使用以下对象,因为您只有一对对象的一半:
{
//First pair
message1: string;
// minLength1: number; // Error †
// ...
}
†错误:如果包含message1
,则还必须包含minLength1
答案 0 :(得分:1)
对于给定的一对属性,您可以最接近地同时需要这两个属性,或者都不是同时具有这两个属性的类型和一个具有never
类型的可选属性的类型的联合(这可防止属性出现的值为undefined
以外的值)。我的想法来自this answer。在正确的情况下,这将给您带来错误,尽管错误消息可能不是特别有用。然后,您可以将所有所需属性对的并集相交(只要您不超过10个对,因为当TypeScript简化类型时,它将分布并集的相交以形成相交的并集,这将爆炸地扩大类型的大小)。例如:
type AllOrNone<T> = T | {[K in keyof T]?: never};
type MyType = AllOrNone<{
message1: string;
minLength1: number;
}> & AllOrNone<{
message2: string;
minLength2: number;
}>;
如果您真的对undefined
案例感到不安,并且愿意使用通用函数来验证对象而不是写下单个类型,那么您可以执行以下操作:
type CheckAllOrNone<A, T> =
T | (keyof A & keyof T extends never ? {} : never);
type CheckMyType<A> = CheckAllOrNone<A, {
message1: string;
minLength1: number;
}> & CheckAllOrNone<A, {
message2: string;
minLength2: number;
}>;
function checkMyType<A extends CheckMyType<A>>(arg: A) {
return arg;
}