打字稿模板文字将数组转换为列表

时间:2021-01-26 09:59:02

标签: typescript

我有一个数组:

 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);

2 个答案:

答案 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);

Playground link

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(',')

Playground Link