azt*_*ack 10 generics typescript template-literals
是否可以在 TypeScript 中生成字符串文字与模板文字组合的排列?
type MetaKey = 'meta';
type CtrlKey = 'ctrl';
type ShiftKey = 'shift';
type AltKey = 'alt';
type ModiferKeyCombinations = ???
Run Code Online (Sandbox Code Playgroud)
预期ModiferKeyCombinations为:
type ModiferKeyCombinations =
| 'meta'
| 'ctrl'
| 'shift'
| 'alt'
| 'meta ctrl'
| 'meta shift'
| 'meta alt'
| 'ctrl meta'
| 'ctrl shift'
| 'ctrl alt'
| 'shift meta'
| 'shift ctrl'
| 'shift alt'
| 'alt meta'
| 'alt ctrl'
| 'alt shift'
| 'meta ctrl shift'
| 'meta ctrl alt'
| 'meta shift ctrl'
| 'meta shift alt'
| 'meta alt ctrl'
| 'meta alt shift'
| 'ctrl meta shift'
| 'ctrl meta alt'
| 'ctrl shift meta'
| 'ctrl shift alt'
| 'ctrl alt meta'
| 'ctrl alt shift'
| 'shift meta ctrl'
| 'shift meta alt'
| 'shift ctrl meta'
| 'shift ctrl alt'
| 'shift alt meta'
| 'shift alt ctrl'
| 'alt meta ctrl'
| 'alt meta shift'
| 'alt ctrl meta'
| 'alt ctrl shift'
| 'alt shift meta'
| 'alt shift ctrl'
| 'meta ctrl shift alt'
| 'meta ctrl alt shift'
| 'meta shift ctrl alt'
| 'meta shift alt ctrl'
| 'meta alt ctrl shift'
| 'meta alt shift ctrl'
| 'ctrl meta shift alt'
| 'ctrl meta alt shift'
| 'ctrl shift meta alt'
| 'ctrl shift alt meta'
| 'ctrl alt meta shift'
| 'ctrl alt shift meta'
| 'shift meta ctrl alt'
| 'shift meta alt ctrl'
| 'shift ctrl meta alt'
| 'shift ctrl alt meta'
| 'shift alt meta ctrl'
| 'shift alt ctrl meta'
| 'alt meta ctrl shift'
| 'alt meta shift ctrl'
| 'alt ctrl meta shift'
| 'alt ctrl shift meta'
| 'alt shift meta ctrl'
| 'alt shift ctrl meta'
Run Code Online (Sandbox Code Playgroud)
jca*_*alz 16
您可以让编译器计算此类排列,但由于排列数量随着元素数量呈指数增长,因此您应该小心使用它。我将按以下步骤进行:
type Permutations<T extends string, U extends string = T> =
T extends any ? (T | `${T} ${Permutations<Exclude<U, T>>}`) : never;
Run Code Online (Sandbox Code Playgroud)
然后你想要的类型是传递你想要排列的字符串的并集Permutations:
type ModiferKeyCombinations = Permutations<MetaKey | CtrlKey | ShiftKey | AltKey>;
Run Code Online (Sandbox Code Playgroud)
您可以通过使用该类型和问题中手动创建的类型多次声明 a 来验证它们是否是同一类型var,并查看编译器对此感到满意:
var x: ModiferKeyCombinations;
var x: ManualModiferKeyCombinations; // no compiler error
Run Code Online (Sandbox Code Playgroud)
方法Permutations<T>是这样的:首先,我必须给它完全并集两次;一次作为T参数,一次作为U参数。这是因为我们需要将这个联合拆成碎片,同时维护它,以便我们可以删除一个具有实用Exclude程序类型的元素。这个想法是获取T完整联合的每个部分U,然后单独返回该部分并使用模板文字字符串类型Permutations<Exclude<U, T>>连接到末尾
如果你调用Permutations<T>when Tis never(意味着零字符串),你就会退出never。
如果您调用Permutations<T>whenT是一个类似于 的字符串"oneString",那么您可以将其用作Permutations<never>答案的一部分: ...根据模板文字字符串的规则,"oneString" | `oneString ${never}`后者将变成其本身。never所以就"oneString"。
如果您调用Permutations<T>whenT是两个字符串的并集,例如"a" | "b",那么您可以使用Permutations<"a">andPermutations<"b">作为答案的一部分:"a" | `a ${Permutations<"b">}` | "b" | `b ${Permutations<"a">}`,它变为"a" | "a b" | "b" | "b a"。
...等等;我就到此为止。