【问题标题】:How to declare a generic type with same keys as an enum?如何声明具有与枚举相同键的泛型类型?
【发布时间】:2021-07-05 02:20:03
【问题描述】:

简介

我有一个enum 并希望将其值映射到更具描述性的字符串。我还希望编译器能够识别我何时错过了映射。所以我做了这样的事情:

enum Foo { A, B }

const fooDescriptions: {[key in Foo]: string} = {
    [Foo.A]: 'Option A',
    [Foo.B]: 'Option B',
}

这按预期工作。现在我想声明一个更具表现力的泛型类型来替换{[key in Foo]: string}(并不是说它会那么难以理解,只是想让事情变得闪亮)。

我的最终目标是这样的泛型类型

type EnumDescriptionType<T> = /* ??? */;
const fooDescriptions: EnumDescriptionType<Foo> = { /* keys of Foo */ };

以下所有代码也可以在TS playground上转载。

尝试 1

type EnumDescriptionType1<T> = { [key in T]: string };

产生错误

Type 'T' is not assignable to type 'string | number | symbol'.
  Type 'T' is not assignable to type 'symbol'.

我真的不明白为什么。我习惯了 C++ 模板,还没有完全理解 typescript 的泛型类型系统。

尝试 2

type EnumDescriptionType2<T> = { [key in keyof T]: string };

const localFooDescriptions2: EnumDescriptionType2<Foo> = fooDescriptions;

产生错误

Type '{ 0: string; 1: string; }' is not assignable to type 'EnumDescriptionType2<Foo>'.
  Type '{ 0: string; 1: string; }' is not assignable to type 'Foo.B'.

在这一点上,老实说,我只是在尝试一些事情,而不了解我做了什么。非常感谢您的澄清。

实际问题

我也读过this question,但他们不使用模板。呜呜呜……

...如何声明像{[key in Foo]: string} 这样的类型,其中Foo 是可以替换为任何枚举的泛型参数?

【问题讨论】:

    标签: typescript


    【解决方案1】:

    您需要确保 T 可以是键,因此在第一次尝试时,您可以通过将其更改为:

    type EnumDescriptionType1<T extends keyof any> = { [key in T]: string };
    

    另外,一个建议,在这种情况下,您可以使用内置的Record 类型:

    type EnumDescriptionType1<T extends keyof any> = Record<T, string>;
    

    您可以用明确的string | symbol | number 替换keyof any,但在这种情况下,IMO keyof any 提供了更易读的代码。

    【讨论】:

    • 在我看来这很神奇,但它确实有效 :D 感谢您的快速回复,一旦系统允许,我会尽快接受。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多