示例:
type DefaultTheme = {
name: 'default';
colors: [string, string, string];
};
type CustomTheme = {
name: 'custom';
colors: [string, string, string, string, string];
};
type DefaultColor = ???; // 'default-1' | 'default-2' | 'default-3';
type CustomColor = ???; // 'custom-1' | 'custom-2' | 'custom-3' | 'custom-4' | 'custom-5';问题是,是否可以使用colors数组的长度来创建映射的联合类型,如给定的示例所示。
为了(希望)清晰起见,简化了这个示例,但是完整地,有一个泛型类型Theme,它使用name和length参数,并使用length生成固定数目的字符串的元组。
发布于 2021-11-22 11:16:41
我简化了@Aleksey L.的解决方案,并采取了不同的方法:
type Indices<T> = keyof T & `${number}`;
type Indices1<T extends [...any]> = Exclude<Indices<[...T, any]>, '0'>
type N_Test = Indices1<[string, string, string]> // '1' | '2' | '3'
type P_Test = `Test-${N_Test}`; // "Test-1" | "Test-2" | "Test-3"主要不同之处:
{ [key in ...]: ... }X extends Y ? ... : ... (Exclude在内部使用这个类型,但它是一个很好的抽象)应用于该示例:
type DefaultTheme = {
name: 'default';
colors: [string, string, string];
};
type CustomTheme = {
name: 'custom';
colors: [string, string, string, string, string];
};
type WithPrefix<T extends {name: string, colors: string[]}> = `${T['name']}-${Indices1<T['colors']>}`;
type DefaultColor = WithPrefix<DefaultTheme>; // 'default-1' | 'default-2' | 'default-3';
type CustomColor = WithPrefix<CustomTheme>; // 'custom-1' | 'custom-2' | 'custom-3' | 'custom-4' | 'custom-5';发布于 2021-11-22 11:03:11
下面是邪恶(代码注释中的一些解释):
// Pick only positive number strings
type Positive<N> = N extends `${number}` ? N extends "0" ? never : N : never
// Produce union of possible array indexes (starting from 1)
type IndexFrom1<T extends Array<any>> = keyof { [K in keyof [null, ...T] as Positive<K>]: any }
type WithPrefix<T extends Array<any>, Prefix extends string, Value = IndexFrom1<T>> =
Value extends string ? `${Prefix}-${Value}` : never
type N_Test = IndexFrom1<[string, string, string]> // "1" | "2" | "3"
type P_Test = WithPrefix<[string, string, string], 'Test'> // "Test-1" | "Test-2" | "Test-3"现在,将WithPrefix util应用于您的示例:
type DefaultTheme = {
name: 'default';
colors: [string, string, string];
};
type CustomTheme = {
name: 'custom';
colors: [string, string, string, string, string];
};
type DefaultColor = WithPrefix<DefaultTheme["colors"], DefaultTheme["name"]>; // 'default-1' | 'default-2' | 'default-3';
type CustomColor = WithPrefix<CustomTheme["colors"], CustomTheme["name"]>; // 'custom-1' | 'custom-2' | 'custom-3' | 'custom-4' | 'custom-5';首先,我们使用映射类型生成元组索引的联合。我们将向它再添加一个成员([null, ...T]),然后删除零索引(N extends "0"),从1开始。
接下来,我们使用分布条件类型和模板文字类型来生成所需的联合。
Value extends string ? `${Prefix}-${Value}` : never发布于 2021-11-22 11:10:02
对于一个非邪恶的解决方案,我们可以使用一个助手类型,它将像[string, string, string]这样的元组转换为像1 | 2 | 3这样的联合。这可以使用元组的length属性递归地完成。
type TupleToUnion<T extends any[]> =
T extends [any, ...infer R] ? T['length'] | TupleToUnion<R> : never
type GenerateUnion<T extends {name: string, colors: string[]}> =
`${T['name']}-${TupleToUnion<T['colors']>}`
// 'default-3' | 'default-2' | 'default-1'
type DefaultColor = GenerateUnion<DefaultTheme>
// 'custom-5' | 'custom-4' | 'custom-3' | 'custom-2' | 'custom-1'
type CustomColor = GenerateUnion<CustomTheme>https://stackoverflow.com/questions/70064173
复制相似问题