如何检查对象中的所有字段是否都是'false'而只有一个是'true'?
How to check whether all fields in an object are 'false' while only one is 'true'?
我有一个包含许多布尔字段的对象,如下所示:
type SomeObject = {
A: boolean
B: boolean
C: boolean
....
}
是否有easy/efficient方法来检查所有其他字段(除了指定字段)的OR
是否为false
?
我们可以通过手动检查每个字段以暴力方式完成:
let foo:SomeObject = {
A: false
B: false
C: false
}
let isA = !(foo.B || foo.C)
let isB = !(foo.A || foo.C)
let isC = !(foo.A || foo.B)
但我确信有更优雅的方法可以完成此任务。
如果您只需要编译时检查,使用映射类型和交集(为“美化”生成的类型而抛出的标识映射类型)非常容易:
type SomeObject = {
A: boolean
B: boolean
C: boolean
}
type OnlyOneTrue<T extends object, K extends keyof T> = {
[P in K] : true
} & {
[P in Exclude<keyof T, K>]: false
};
type Identity<T> = { [P in keyof T] : T[P] }
//{ A: true; } & { B: false; C: false; }
type test = OnlyOneTrue<SomeObject, "A">;
//{ A: true; B: false; C: false; }
type pretty = Identity<test>;
如果你需要编译时类型保护以便以后可以缩小类型,那么你需要使用联合。前一个类型可以成为另一个实用类型的垫脚石:
type PossibleOnlyTrue<T extends object> = {
[P in keyof T]: OnlyOneTrue<T, P>
}[keyof T];
//OnlyOneTrue<SomeObject, "A"> | OnlyOneTrue<SomeObject, "B"> | OnlyOneTrue<SomeObject, "C">
type union = PossibleOnlyTrue<SomeObject>;
const process = (obj: union) => {
//type is narrowed to a union member:
if(obj.A) {
console.log(obj); //OnlyOneTrue<SomeObject, "A">
}
};
如果您需要在顶部进行运行时检查,可以选择。下面是基于之前的辅助映射类型(PossibleOnlyTrue
和 OnlyOneTrue
)的类型和运行时保护:
const runtime = <K extends keyof union>(obj: union, key: K) : obj is Extract<union, { [P in K] : true }> => {
return Object.entries(obj).every(([k,v]) => k === key || !v );
};
{
const obj:union = { A:true, B:false,C:false };
if(runtime(obj, "A")) obj //OK, obj is OnlyOneTrue<SomeObject, "A">
}
我有一个包含许多布尔字段的对象,如下所示:
type SomeObject = {
A: boolean
B: boolean
C: boolean
....
}
是否有easy/efficient方法来检查所有其他字段(除了指定字段)的OR
是否为false
?
我们可以通过手动检查每个字段以暴力方式完成:
let foo:SomeObject = {
A: false
B: false
C: false
}
let isA = !(foo.B || foo.C)
let isB = !(foo.A || foo.C)
let isC = !(foo.A || foo.B)
但我确信有更优雅的方法可以完成此任务。
如果您只需要编译时检查,使用映射类型和交集(为“美化”生成的类型而抛出的标识映射类型)非常容易:
type SomeObject = {
A: boolean
B: boolean
C: boolean
}
type OnlyOneTrue<T extends object, K extends keyof T> = {
[P in K] : true
} & {
[P in Exclude<keyof T, K>]: false
};
type Identity<T> = { [P in keyof T] : T[P] }
//{ A: true; } & { B: false; C: false; }
type test = OnlyOneTrue<SomeObject, "A">;
//{ A: true; B: false; C: false; }
type pretty = Identity<test>;
如果你需要编译时类型保护以便以后可以缩小类型,那么你需要使用联合。前一个类型可以成为另一个实用类型的垫脚石:
type PossibleOnlyTrue<T extends object> = {
[P in keyof T]: OnlyOneTrue<T, P>
}[keyof T];
//OnlyOneTrue<SomeObject, "A"> | OnlyOneTrue<SomeObject, "B"> | OnlyOneTrue<SomeObject, "C">
type union = PossibleOnlyTrue<SomeObject>;
const process = (obj: union) => {
//type is narrowed to a union member:
if(obj.A) {
console.log(obj); //OnlyOneTrue<SomeObject, "A">
}
};
如果您需要在顶部进行运行时检查,可以选择。下面是基于之前的辅助映射类型(PossibleOnlyTrue
和 OnlyOneTrue
)的类型和运行时保护:
const runtime = <K extends keyof union>(obj: union, key: K) : obj is Extract<union, { [P in K] : true }> => {
return Object.entries(obj).every(([k,v]) => k === key || !v );
};
{
const obj:union = { A:true, B:false,C:false };
if(runtime(obj, "A")) obj //OK, obj is OnlyOneTrue<SomeObject, "A">
}