typescript,有没有办法去分割字符串,并且拿到具体的类型啊?

比方说这样 type A = 'AaBb' | 'CcDdEe'; type B = ... // 经过一些操作使得B 类型为 'Aa-Bb' | '…
关注者
5
被浏览
3,863

1 个回答

具体例子

你提问中这个例子可以通过 TS 4.1 引入的 Template Literal Types 轻松解决。我们一个字符一个字符看就好了,具体看注释:

type A = "AaBb" | "CcDdEe";
// 经过一些操作使得B 类型为 'Aa-Bb' | 'Cc-Dd-Ee'
type B = SplitAndJoin<A>;
type SplitAndJoin<
  Acc extends string = ""
> = S extends `${infer H}${infer Rest}` // 看第一个字符
  ? SplitAndJoin<
      Rest,
      H extends Uppercase<H> // H 是大写
        ? Acc extends "" // H 是第一个字母
          ? `${H}`
          : `${Acc}-${H}`
        : `${Acc}${H}`
  : Acc; // S 为空,返回 accumulator 的结果

以下是结果,你可以去试试: TS Playground - An online editor for exploring TypeScript and JavaScript

结果

更通用的写法

如果我们写得更通用,更灵活一点,可以去支持用任意字符去 split 和 join。这里的 Separators 可以是一个 Union。你这个例子与常见的 String.prototype.split() 的不同之处在于,你保留了 separator,那我们可以增加一个参数,来控制是否保留。

来试试: TS Playground - An online editor for exploring TypeScript and JavaScript

通用的 Split 和 Join
type Split<
  TString,
  TSep,
  TPreserveSep extends boolean = false,
  Acc extends string = "", // 用来存放每一组 string
  Res extends string[] = [] // 最终结果,一组组拆好的 string
> = TString extends `${infer H}${infer Rest}`
  ? H extends TSep
    ? Split<
        Rest,
        TSep,
        TPreserveSep,
        [...Res, `${Acc}${TPreserveSep extends true ? H : ""}`]
      > // H 是个 separator,清空现有的 string accumulator,把得到的一组加入结果 array 里
    : Split<Rest, TSep, TPreserveSep, `${Acc}${H}`, Res> // H 不是 separator,存进 string accumulator 备用,直到遇到下一个 sep
  : Res;
type Join<
  TArr extends unknown[],
  TSep extends string,
  Acc extends string = ""
> = TArr extends [infer H, ...infer Rest] // 拿到第一个 element
  ? Join<