我试图创建一个pair类型,它只允许从给定的字符串联合中分配匹配的值。
首先,我已经可以从给予const数组创建一个字符串联合:
const allFoos = ['foo', 'bar', 'baz'] as const;
// Creates a string union of ('foo' | 'bar' | 'baz')
type Foo = typeof allFoos[number];
另外,我可以创建一个元组,它只允许分配这个联合的成员。
// Creates a tuple allow any two of Foo to be assigned
type Pair = readonly [Foo, Foo];
const good: Pair = ['foo', 'bar']; // Assigns fine
const bad: Pair = ['foo', 'zzz']; // Compile error
理想情况下,我想要一个只允许相同值的元组类型。
显然,我可以通过手写指定所有结果:
type HandWrittenMatchedPair =
| readonly ['foo', 'foo']
| readonly ['bar', 'bar']
| readonly ['baz', 'baz'];
const good: HandWrittenMatchedPair = ['foo', 'foo']; // Assigns fine
const bad: HandWrittenMatchedPair = ['foo', 'baz']; // Compile error
添加的元素越多,手写所有变体的可行性就越小。同样对于N个元素元组,它变得更加乏味,所以理想情况下应该生成这些类型:
// How to do this without handwriting every possibility?
type MatchedPair = [???];
// Ideal outcome
const good: MatchedPair = ['foo', 'foo']; // Should assign fine
const bad: MatchedPair = ['foo', 'bar']; // Should result in compile error
我想做的事情可能吗?
1条答案
按热度按时间sczxawaw1#
您希望定义
Pair
,以便它自动地将“turnT
intoreadonly [T, T]
”操作 * 分发 * 到Foo
联合体上。有几种方法可以做到这一点:由于
Foo
的成员是类键的(字符串文字类型"foo"
、"bar"
和"baz"
可以是对象的键),您可以编写 * 分布式对象类型 *(如ms/TS#47109中所创造的),这是您在成员上创建mapped type,就好像它们是对象键一样,然后立即index into该Map类型以获得属性值的并集。像这样:或者,对于任意联合(其成员可能不是keylike),您可以编写一个分布式条件类型,其中检查类型是泛型类型参数,如下所示:
(Note在上面的例子中,
T
是泛型类型参数,而Foo
* 不是 * 泛型类型参数。不能将其缩短为Foo extends unknown ? readonly [Foo, Foo] : never
。我使用条件类型infer
ence的全部原因是将Foo
复制到泛型类型参数T
,以便内部条件类型是分布式的。无论哪种方式
如果
Foo
的定义更新,则其将自动更新。Playground链接到代码