Skip to content

重新构造

type、infer、类型参数声明的变量都不能修改,想对类型做各种变换产生新的类型就需要重新构造

数组

把以下两个元组合并成另一个元组

typescript
type a = [1, 2]
type b = ['1', '2']

type c = [[1, '1'], [2, '2']]

则可以如下重新构造

typescript
type Zip<One extends [unknown, unknown], Two extends [unknown, unknown]> =
    One extends [infer OneF, infer OneT]
        ? Two extends [infer TwoF, infer TwoT]
            ? [[OneF, TwoF], [OneT, TwoT]]
            : []
        : []

字符串

实现 dong_dong 到 dongDong 的变换

小写到大写的转换可以用到内置高级类型 Uppercase

typescript
type camelCase<S extends string> = 
    S extends `${infer Prefix}_${infer C}${infer Rest}`
        ? `${Prefix}${Uppercase<C>}${Rest}`
        : S

函数

在已有的函数类型上添加一个参数

typescript
type AppendArgument<Func extends Function, Arg> = 
    Func extends (...args: infer Args) => infer ReturnType 
        ? (...args: [...Args, Arg]) => ReturnType
		: never

索引

  1. 重新构造 value
typescript
type Mapping<Obj extends object> = { 
    [Key in keyof Obj]: [Obj[Key], Obj[Key], Obj[Key]]
}
  1. 重新构造 key,被称为 重映射
typescript
type UppercaseKey<Obj extends object> = { 
    [Key in keyof Obj as Uppercase<Key & string>]: Obj[Key]
}

因为索引可能为 string、number、symbol 类型,而这里只能接受 string 类型,所以要 & string,也就是取索引中 string 的部分

索引类型的约束用的 object,其实更语义化一点推荐用 Record<string, any>

typescript
type UppercaseKey<Obj extends Record<string, any>> = { 
    [Key in keyof Obj as Uppercase<Key & string>]: Obj[Key]
}