【问题标题】:Force a boolean property to be true or false using mapped types in Typescript使用 Typescript 中的映射类型强制布尔属性为真或假
【发布时间】:2018-11-24 08:35:57
【问题描述】:

我有一个包含布尔属性(以下称为booleanProp)的接口(以下称为Foo)。鉴于此,我想将其包装在映射类型中,以便能够将变量类型限制为 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 子句都能正常工作。有什么建议吗?

(注意:我知道避免使用映射类型的替代选项,无需指出)

【问题讨论】:

  • 这个检查:if (falseFoo.booleanProp === true)只限制booleanProp的类型,不限制falseFoo的类型,除非falseFoo类型是可判别联合,判别器是booleanProp ,正如提香所说,这是他的答案。

标签: typescript mapped-types


【解决方案1】:

这种基于检查的缩小类型的行为所涉及的特性是可区分联合。在没有联合的情况下,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
    };
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-06-23
    • 2018-03-19
    • 1970-01-01
    • 1970-01-01
    • 2021-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多