【问题标题】:Map all tags of a tagged union type in TypeScript在 TypeScript 中映射标记联合类型的所有标签
【发布时间】:2019-06-14 18:04:22
【问题描述】:

是否可以将标记联合类型的所有标记映射到数组中?假设我们有以下类型:

type Options = Cash | PayPal | CreditCard;    

interface Cash {
  kind: "cash";
}

interface PayPal {
  kind: "paypal";
  email: string;
}

interface CreditCard {
  kind: "credit";
  cardNumber: string;
  securityCode: string;
}

是否可以将所有鉴别器kind 收集到一个字符串数组中?结果应该类似于['cash', 'paypal', 'credit']

提前谢谢你!

【问题讨论】:

    标签: typescript union-types


    【解决方案1】:

    没有办法从标准打字稿中的类型获取值(可能有一些非官方的语言扩展允许这样做)

    你可以得到一个类型是所有kinds的联合:

    type OptionsKind = Options['kind'] //  "cash" | "paypal" | "credit"
    

    您还可以构建一个必须具有联合的所有属性的对象,并使用Object.keys 从该对象中获取一个数组:

    type OptionsKind = Options['kind'] //  "cash" | "paypal" | "credit"
    let OptionsKind: { [P in OptionsKind]: 1 } = {
        cash: 1,
        credit: 1,
        paypal: 1        
    }
    let OptionsKindArray = Object.keys(OptionsKind);
    

    如果对象中有任何额外的键、对象中没有所有键以及任何键拼写错误,此解决方案将确保您收到错误消息。所以基本上它可以确保重复数据至少始终是最新的。

    您甚至可以为任何联合创建一个辅助函数:

    type OptionKinds = Options['kind'] //  "cash" | "paypal" | "credit"
    function unionValues<T extends string>(o: Record<T, 1>) {
        return Object.keys(o) as T[];
    }
    
    let OptionKinds = unionValues<OptionKinds>({ cash: 1, paypal: 1, credit: 1 }); 
    

    【讨论】:

    • 谢谢@Titian!我已经对其进行了测试并且它可以工作,但是它有点难看。鉴别器 kind 可以以某种方式替换为枚举吗?也许这会导致更清洁的解决方案?你怎么看?
    • @Robin 你可以用枚举替换kind 属性。虽然我不认为这会减少很多重复(你仍然需要单独定义枚举并在接口定义中使用它,你也不能确定枚举将只包含使用成员(枚举成员可能不是由接口使用,不会引发错误)。但任何一种方式都可以工作。
    猜你喜欢
    • 2019-01-12
    • 2018-08-14
    • 2019-01-27
    • 2020-09-22
    • 1970-01-01
    • 1970-01-01
    • 2023-03-13
    • 2022-07-27
    • 1970-01-01
    相关资源
    最近更新 更多