我有一个数组:
const arr = ['a', 'b', 'c']
我想转换为逗号分隔的列表 - 'a,b,c'
。有什么方法可以使用新的 Template Literals 功能转换它的类型吗?
function toList<T>(arr: T[]) {
return arr.join(',')
}
const list: 'a,b,c' = toList(arr);
答案 0 :(得分:2)
这是您的解决方案:
const arr = ['a', 'b', 'c'] as const;
type Arr = typeof arr;
type Elem = string
type Mapper<
Arr extends ReadonlyArray<Elem>,
Result extends string = ''
> = Arr extends []
? Result
: Arr extends [infer H]
? H extends Elem
? `${Result},${H}`
: never
: Arr extends readonly [infer H, ...infer Tail]
? Tail extends ReadonlyArray<Elem>
? H extends Elem
? Result extends '' ? Mapper<Tail, `${Result}${H}`> : Mapper<Tail, `${Result},${H}`>
: never
: never
: never;
type Result = Mapper<Arr> // "a,b,c"
function toList<T extends ReadonlyArray<string>>(arr: T) {
return arr.join(',') as Mapper<T>
}
const list = toList(arr);
Here 你可以找到更多有趣的例子
附言请记住,它不是 100% 类型安全的,因为我使用了强制转换运算符 as
答案 1 :(得分:1)
我已更新 captain-yossarian 示例以扩展 ReadonlyArray 接口。 这种方法避免了强制转换语句。
const list = ['a', 'b', 'c'] as const;
type Join<
List extends ReadonlyArray<string>,
Seperator extends string = ',',
Joined extends string = ''
> = List extends []
? Joined
: List extends [infer Head]
? Head extends string
? `${Joined}${Seperator}${Head}`
: never
: List extends readonly [infer Head, ...infer Tail]
? Tail extends ReadonlyArray<string>
? Head extends string
? Joined extends '' ? Join<Tail, Seperator, `${Joined}${Head}`> : Join<Tail, Seperator, `${Joined}${Seperator}${Head}`>
: never
: never
: never;
interface ReadonlyArray<T extends string> {
join<Separator extends string, This extends ReadonlyArray<T>>(this: This, separator: Separator): Join<This, Separator>
}
const joined = list.join(',')