使用 Typescript 中的映射类型强制布尔值 属性 为真或假
Force a boolean property to be true or false using mapped types in Typescript
我有一个接口(以下称为 Foo
),它包含一个布尔值 属性(以下称为 booleanProp
)。鉴于此,我想将其包装在映射类型中,以便能够将变量的类型限制为 Foo
对象 属性 booleanProp
设置为 true
,或者false
。
示例如下:
interface Foo {
readonly booleanProp: boolean;
}
type BooleanPropIsTrue<T extends { readonly booleanProp: boolean }> = {
readonly [ P in keyof T]: T[P];
} & {
readonly booleanProp: true;
};
const falseFoo: Foo = {
booleanProp: false
};
const trueFoo: Foo = {
booleanProp: true
};
if (falseFoo.booleanProp === true) {
// ERROR: type 'boolean' is not assignable to type 'true'.
const foo: BooleanPropIsTrue<Foo> = falseFoo;
}
if (trueFoo.booleanProp === true) {
// ERROR: type 'boolean' is not assignable to type 'true'.
const foo: BooleanPropIsTrue<Foo> = trueFoo;
}
if (trueFoo.booleanProp === true) {
// Works
const foo: BooleanPropIsTrue<Foo> = {
...trueFoo,
booleanProp: true
};
}
我希望所有 3 个 if 子句都能工作。有什么建议吗?
(注意:我知道避免使用映射类型的替代选项,无需指出)
这种基于检查缩小类型的行为所涉及的特征是discriminated union。在没有联合的情况下,Typescript 不会跟踪此类检查(因为就编译器而言,没有潜在的类型缩小)。简单的解决方法是将 Foo
转换为可区分的联合:
type Foo = {
booleanProp: true;
} | {
booleanProp: false;
}
type BooleanPropIsTrue<T extends { readonly booleanProp: boolean }> = {
readonly [ P in keyof T]: T[P];
} & {
readonly booleanProp: true;
};
// We introduce some randomness, if we assign { booleanProp: false } we can't even do the check as the compiler will know booleanProp is always false
const falseFoo: Foo = Math.random()> 0.5 ? {
booleanProp: false
} : {
booleanProp: true
};
const trueFoo: Foo = {
booleanProp: true
};
if (falseFoo.booleanProp === true) {
//Works
const foo: BooleanPropIsTrue<Foo> = falseFoo;
}
if (trueFoo.booleanProp === true) {
//Works
const foo: BooleanPropIsTrue<Foo> = trueFoo;
}
if (trueFoo.booleanProp === true) {
// Works
const foo: BooleanPropIsTrue<Foo> = {
...trueFoo,
booleanProp: true
};
}
我有一个接口(以下称为 Foo
),它包含一个布尔值 属性(以下称为 booleanProp
)。鉴于此,我想将其包装在映射类型中,以便能够将变量的类型限制为 Foo
对象 属性 booleanProp
设置为 true
,或者false
。
示例如下:
interface Foo {
readonly booleanProp: boolean;
}
type BooleanPropIsTrue<T extends { readonly booleanProp: boolean }> = {
readonly [ P in keyof T]: T[P];
} & {
readonly booleanProp: true;
};
const falseFoo: Foo = {
booleanProp: false
};
const trueFoo: Foo = {
booleanProp: true
};
if (falseFoo.booleanProp === true) {
// ERROR: type 'boolean' is not assignable to type 'true'.
const foo: BooleanPropIsTrue<Foo> = falseFoo;
}
if (trueFoo.booleanProp === true) {
// ERROR: type 'boolean' is not assignable to type 'true'.
const foo: BooleanPropIsTrue<Foo> = trueFoo;
}
if (trueFoo.booleanProp === true) {
// Works
const foo: BooleanPropIsTrue<Foo> = {
...trueFoo,
booleanProp: true
};
}
我希望所有 3 个 if 子句都能工作。有什么建议吗?
(注意:我知道避免使用映射类型的替代选项,无需指出)
这种基于检查缩小类型的行为所涉及的特征是discriminated union。在没有联合的情况下,Typescript 不会跟踪此类检查(因为就编译器而言,没有潜在的类型缩小)。简单的解决方法是将 Foo
转换为可区分的联合:
type Foo = {
booleanProp: true;
} | {
booleanProp: false;
}
type BooleanPropIsTrue<T extends { readonly booleanProp: boolean }> = {
readonly [ P in keyof T]: T[P];
} & {
readonly booleanProp: true;
};
// We introduce some randomness, if we assign { booleanProp: false } we can't even do the check as the compiler will know booleanProp is always false
const falseFoo: Foo = Math.random()> 0.5 ? {
booleanProp: false
} : {
booleanProp: true
};
const trueFoo: Foo = {
booleanProp: true
};
if (falseFoo.booleanProp === true) {
//Works
const foo: BooleanPropIsTrue<Foo> = falseFoo;
}
if (trueFoo.booleanProp === true) {
//Works
const foo: BooleanPropIsTrue<Foo> = trueFoo;
}
if (trueFoo.booleanProp === true) {
// Works
const foo: BooleanPropIsTrue<Foo> = {
...trueFoo,
booleanProp: true
};
}