【问题标题】:Building mapped exclusive type in typescript在打字稿中构建映射的独占类型
【发布时间】:2021-09-10 20:37:45
【问题描述】:

我有以下类型(简体):

type ValueRepresents = {
    boolean: true
    number?: false
    other?: false
} |
{
    boolean?: false
    number: true
    other?: false
} |
{
    boolean?: false
    number?: false
    other: true
}

我的实际类型有更多可能的键。有没有办法从可能的键列表中生成这种类型,以使只有一个键的值设置为 true 才有效?比如:

type ValueTypes = "boolean" | "number" | "other"
type ValueRepresents <T extends ValueTypes> = {
    [k in ValueTypes]: k extends T ? true : false
}
const a: ValueRepresents<"boolean"> = {
    boolean: true,
    number: false,
    other: false,
}

但我的目标是能够使用:

// should pass
const a: ValueRepresents = { boolean: true }

// should pass
const a2: ValueRepresents = {
    boolean: true,
    number: false,
}

// should error
const a3: ValueRepresents = {
    boolean: true,
    number: true,
}

// should error
const a4: ValueRepresents = {}

我也尝试了following this answer,但还没有成功:

type ValueRepresents <T extends ValueTypes> = {
    [k in Exclude<T, ValueTypes>]?: false
} & { [k in T]: true }

【问题讨论】:

    标签: typescript mapped-types


    【解决方案1】:

    您可以尝试创建这样的联合类型

    type ValueTypes = "boolean" | "number" | "other"
    
    type ValueRepresents = ({
        [K in ValueTypes]: Partial<Record<Exclude<ValueTypes, K>, false>> & Record<K, true>
    })[ValueTypes]
    

    TypeScript Playground


    TL;DR

    我认为这个表达式没有特定的名称。我在the docs in Advanced Types 中看到过类似的示例,但我会尝试解释它是如何工作的。

    type ValueRepresents = {
        [K in ValueTypes]: Partial<Record<Exclude<ValueTypes, K>, false>> & Record<K, true>
    }
    

    创建类型等价于:

    type ValueRepresents = {
      boolean: {
        boolean: true;
        number?: false;
        other?: false;
      };
      number: {
        boolean?: false;
        number: true;
        other?: false;
      };
      other: {
        boolean?: false;
        number?: true;
        other: true;
      };
    };
    

    并通过在方括号[ValueTypes] 中添加联合类型,它会在另一个联合类型中提取这些(所有)键的值,相当于:

    type ValueRepresents =
      | {
          boolean: true;
          number?: false;
          other?: false;
        }
      | {
          boolean?: false;
          number: true;
          other?: false;
        }
      | {
          boolean?: false;
          number?: true;
          other: true;
        };
    

    【讨论】:

    • 这太棒了。谢谢你。我在)[ValueTypes] 之前从未见过这种语法,你能指点我一些解释它的文档吗?我现在玩弄它,所以我对它的作用有部分感觉,但我不知道它叫什么。
    • @AJP 我已经添加了关于它如何工作的简短说明
    猜你喜欢
    • 2019-11-19
    • 1970-01-01
    • 2022-12-07
    • 2018-06-16
    • 2022-01-06
    • 2022-08-17
    • 1970-01-01
    • 2019-12-11
    • 2022-08-16
    相关资源
    最近更新 更多