【问题标题】:Use an enum to type an index signature of an interface field?使用枚举键入接口字段的索引签名?
【发布时间】:2019-04-29 17:27:04
【问题描述】:

我可以用如下的对象类型表示法来描述索引类型限制:

enum Enum {
    A = 0,
    B = 1,
}

type EnumMap = {
    [P in Enum]: string;
}

但是,令人惊讶的是,在接口中使用索引表示法时似乎不可能做到这一点:

enum Enum {
    A = 0,
    B = 1,
}

interface EnumMap {
    [P in Enum]: string;
}

错误是:

计算属性名称的类型必须为“字符串”、“数字”、“符号”或“任意”。

有什么理由会这样吗?根据定义,TypeScript 中的枚举只能有字符串或数字值(甚至两者都有,但不推荐这样做),我认为枚举本身对于它列出的所有值都可以像联合类型一样工作。


进一步调查,我还发现,在以下示例中,EnumValues 的类型为 number,而不是(我期望的)0 | 1。再说一遍,为什么会这样?

const Enum = {
    A: 0,
    B: 1
};

type EnumKeys = keyof typeof Enum;
type EnumValues = typeof Enum[EnumKeys];

【问题讨论】:

标签: typescript enums interface typescript2.0


【解决方案1】:

关于错误:

interface EnumMap {
    [P in Enum]: string;
}

枚举是 TypeScript 中的一种特殊数据结构,它不能分配给 string | number | symbol。 考虑这个例子:

const key = <T extends string | number | symbol>(t: T) => t

key(Enum) // error

另外,enum 有特殊行为。

看这个例子:

const enm = (t: Enum) => t

// Argument of type 'typeof Enum' is not assignable to parameter of type 'Enum'
enm(Enum) // error

所以即使Enumtypeof Enum 之间也存在差异。

让我们回到我们的问题。 在TS 4.4 之前,您不得在接口中使用联合作为索引签名。 考虑这个没有enum的例子:

interface EnumMap {
    [P in 'a'|'b']: string; // error
}

因此它是关于 TS 限制而不是关于枚举。

至于第二种情况:

const Enum = {
    A: 0,
    B: 1
};

type EnumKeys = keyof typeof Enum;
type EnumValues = typeof Enum[EnumKeys];

这是因为const Enum 是可变的。

为了获得1|0,你应该让它不可变:

const Enum = {
    A: 0,
    B: 1
} as const; // special syntax

type EnumKeys = keyof typeof Enum;
type EnumValues = typeof Enum[EnumKeys]; // 0 | 1

【讨论】:

    猜你喜欢
    • 2011-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-03
    相关资源
    最近更新 更多