声明变量,其键为两种类型的串联

时间:2018-07-09 14:19:12

标签: typescript ecmascript-6

我想通过声明对象中的键是两种类型的串联来锁定对象的创建。由于模糊,让我用一些代码来描绘它:

type Letter = 'A' | 'B' | 'C';

boxes: { [ID in Letter]: string }[] = ...;

现在,此代码允许一个人创建一组这样的盒子:

boxes = [{ A: 1 }]; // Correct
boxes = [{ D: 1 }]; // Incorrect

我想要实现的是做同样的事情,但是在键中包含数字。像这样:

type Letter = 'A' | 'B' | 'C';
type Digit = '0' | '1' | '2';

boxes: { [ID in (Letter + '-' + Digit)]: string }[] = ...;

然后用户可以在此处创建

boxes = { 'A-1': 1 };

是否可以?如果可以,如何?

PS:键必须是动态的,即我无法声明由所有可能的组合组成的新类型

2 个答案:

答案 0 :(得分:2)

A-1字符串需要在运行时评估(Letter + '-' + Digit)。在TypeScript中无法实现此类键的类型安全。

如果需要类型安全,则不能将A-1之类的键视为适当的方式。

答案 1 :(得分:1)

这是不可能的,不支持对字符串文字的操作。

如果您的字符串集有限(如提供的示例所示),那么最好的选择是生成所有组合(不应那么多,并且可以编写脚本来生成它们)

如果有很多可能的组合,那么仅使用简单的索引签名可能会做得更好。

另一种方法是,以索引的第二部分实际上是嵌套对象的方式重新定义数据结构,它比较冗长,但类型安全:

type Letter = 'A' | 'B' | 'C';
type Digit = '0' | '1' | '2';

type UnionOfJustOneProperty<T extends string, TAll extends string> = T extends string ? { [P in T]: string } & { [P in Exclude<TAll, T>]?: never }: never;
let boxes: { [P in Letter]: UnionOfJustOneProperty<Digit,Digit> }[] = [
    { 
        A: { "0": "value"},
        B: { "1": "value"},
        C: { "0": "value", /* "1": "" */} // the commented code causes an error, we can only have one key in the object
    }
];