ts类型体操学习笔记

typescript 类型体操学习笔记

// typescript demo
type TrimRight<T extends string> = T extends `${infer Rest}${' ' | '\n' | '\t'}` ? TrimRight<Rest> : T
type TrimLeft<T extends string> = T extends `${' ' | '\n' | '\t'}${infer Rest}` ? TrimLeft<Rest> : T

type str = '   asd   '
type ms = TrimLeft<str>

// TODO: 逆变性质 参数为何使用any[] 而不是unknow[]
type GetReturnType<Fn extends Function> = Fn extends (...args: any[]) => infer ReturnType ? ReturnType : never
type ReturnResult = GetReturnType<(a: number, b: string) => number>

type GetThisParameterType<T> = T extends (this: infer ThisType, ...args: any[]) => any ? ThisType : never

class Cat {
  age: 12
  say(this: Cat) {
    console.log(this.age)
  }
}

const cat = new Cat()
// 主要需要开启strictBindCallApply 是否按照原函数的类型来检查bind call apply
cat.say.call({age: 12})
type ThisResult = GetThisParameterType<typeof cat.say>

interface Person {
  name: string
}

interface PersonConstructor {
  new(name: string): Person
}

type GetInstanceType<T extends new (...args: any) => any> = T extends new (...args: any) => infer InstanceType ? InstanceType : any
type GetConstructorParams<T extends new (...args: any) => any> = T extends new (...args: infer ParametersType) => any ? ParametersType : any
type InstanceResult = GetInstanceType<PersonConstructor>
type paramsResult = GetConstructorParams<PersonConstructor>

type GetNameType<T> = 'name' extends keyof T ? T extends { name?: infer NameType | undefined } ? NameType : never : never
type NameResult = GetNameType<{age: 12, name: 'asdf'}>

type Push<T extends unknown[], S> = [...T, S]
type PushResult = Push<[1,2,3], 'adsf'>

type tuple1 = [1,2]
type tuple2 = ['a', 'b']
// 两个长度为2 的元祖进行合并
type Zip<T extends [unknown, unknown], S extends [unknown, unknown]> = T extends [infer TF, infer TL] ? S extends [infer SF, infer SL] ? [[TF, SF], [TL, SL]] : never : never
// 任意数量长度的元祖进行合并
type Zip2<T extends unknown[], S extends unknown[]> = T extends [infer TF, ...infer TR] ? S extends [infer SF, ...infer SR] ? [[TF, SF], ...Zip2<TR, SR>] : [] : []
type ZipResult = Zip<tuple1, tuple2>
type Zip2Result  = Zip2< [1,2,3,4], ['a', 'b','c', 'd']>

type CapitalizeStr<T extends string> = T extends `${infer F}${infer R}` ? `${Uppercase<F>}${R}` : T
type CapitalizeResult = CapitalizeStr<'hello'>

// dong_dong_dong => dongDongDong
type CamelCase<T extends string> = T extends `${infer F}_${infer Right}${infer Rest}` ? `${F}${Uppercase<Right>}${CamelCase<Rest>}` : T
type CamelcaseResult = CamelCase<'dong_dong_dong'>

// 删除指定字符
// 按照索引删除指定字符
type DropSubStr<T extends string, S extends string> = T extends `${infer Prefix}${S}${infer Suffix}` ? DropSubStr<`${Prefix}${Suffix}`, S> : T
type msd = DropSubStr<'abbcdb', 'b'>
type Skip<S extends string, N extends number, A extends string[] = []> = A['length'] extends N ? S : S extends `${infer F}${infer R}` ? Skip<R, N, [...A, F]> : S
type SliceStr<S extends string, B extends number, E extends number> = Skip<S, B> extends `${infer R}${Skip<S, E>}` ? R : never
type SliceStrResult = SliceStr<'abcdefg', 2, 4> // 含头不含尾
type S1 = Skip<'abcdefg', 2>
type S2 = Skip<'abcdefg', 4>

type AppendArgument<Fn extends Function, Arg> = Fn extends (...args: infer Args) => infer ReturnType ? (...args: [...Args, Arg]) => ReturnType : Fn
type AppendArguResult = AppendArgument<(name: string) => number, string>

// type UpperKey<T extends object> = {
//   [key in keyof T as CapitalizeStr<key & string>]: T[key]
// }
type RecordRes<K extends string, T> = { [P in K]: T }
type mb = object
type xx = Record<string, any> extends mb ? true : false
type UpperKey<T extends RecordRes<string, any>> = {
  [key in keyof T as CapitalizeStr<key & string>]: T[key]
}
type UpperResult = UpperKey<{hello: 12, a: 'b'}>

type RecordResult = RecordRes<'a', 12>

type ToMutable<T extends object> = {
  -readonly [K in keyof T]: T[K]
}
type ToRequired<T extends object> = {
  [K in keyof T]-?: T[K]
}
type MutableResult = ToMutable<{readonly age: 12, name: 'asdfa'}>
type RequiredResult = ToRequired<{readonly age?: 12, name: 'asdfa'}>

// 提取多层promise 返回的value
// type DeepGetPromiseValue<P extends Promise<unknown>> = P extends Promise<infer V> ? V extends Promise<unknown> ? DeepGetPromiseValue<V> : V : never
type DeepGetPromiseValue<P> = P extends Promise<infer V> ? DeepGetPromiseValue<V> : P
type t = Promise<Promise<Promise<number>>>
type PromiseValue = DeepGetPromiseValue<t>

type ReverseArr<T extends unknown[]> = T extends [infer F, ...infer R] ? [...ReverseArr<R>, F] : T
type ReverseRestult = ReverseArr<[1,2,3,4,5]>

type Includes<T extends unknown[], F> = T extends [infer First, ...infer R] ? IsEqual<First, F> extends true ? true : Includes<R, F> : false
type IsEqual<A, B> = (A extends B ? true : false) & (B extends A ? true : false)
type IncludeResult = Includes<[1,2,{a: 1}], {a, 1}>

type RemoveItem<T extends unknown[], Item, Result extends unknown[] = []> =
  T extends [infer First, ...infer Rest] ?
    IsEqual<First, Item> extends true ?
      RemoveItem<Rest, Item, Result> :
        RemoveItem<Rest, Item, [...Result, First]>
  : Result
type RemoveResult = RemoveItem<[1,2,3,4], 2>

type BuildArr<Length extends number, Item, Arr extends unknown[] = []> = Arr['length'] extends Length ? Arr : BuildArr<Length, Item, [...Arr, Item]>
type BuildResult = BuildArr<5, 1>


type ReplaceAll<Str extends string, From extends string, To extends string> = Str extends `${infer Left}${From}${infer Right}` ? `${Left}${To}${ReplaceAll<Right, From, To>}` : Str
type ReplaceResult = ReplaceAll<'this is Hello world', 'is', 'id'>

type StringToUnion<Str extends string> = Str extends `${infer F}${infer Rest}` ? F | StringToUnion<Rest> : never
type UnionResult = StringToUnion<'hello'>

type ReverseStr<Str extends string, Result extends string = ''> = Str extends `${infer F}${infer Rest}` ? `${ReverseStr<Rest, Result>}${F}` : Result
type ReverseStrResult = ReverseStr<'abcdefg'>

type DeepReadonly<Obj extends Record<string, any>> = {
  readonly [key in keyof Obj] : Obj[key] extends object ? Obj[key] extends Function ? Obj[key] : DeepReadonly<Obj[key]> : Obj[key]
}

/**
 ts 类型只有被用到的时候才会做计算
 type DeepReadonly<Obj extends Record<string, any>> = Obj extends any ? {
   readonly [key in keyof Obj] : Obj[key] extends object ? Obj[key] extends Function ? Obj[key] : DeepReadonly<Obj[key]> : Obj[key]
 } : never
 */

type ReadonlyResult = DeepReadonly<{a: {b: { c: {d: number} }}}>

const b:ReadonlyResult = {
  a: {
    b: {
      c: {
        d: 12
      }
    }
  }
}


// 数值运算

// 加法
type Add<T extends number, S extends number> = [...BuildArr<T, number>, ...BuildArr<S, number>]['length']
type AddResult = Add<2,3>
// 减法
type Subtract<T extends number, S extends number> = BuildArr<T, number> extends [...arr1:BuildArr<S, number>, ...arr2: infer Rest] ? Rest['length'] : never
type SubtractResult = Subtract<4,1>
// 乘法
type Mutiply<Num1 extends number, Num2 extends number, ResultArr extends unknown[] = []> = Num2 extends 0 ? ResultArr['length'] : Mutiply<Num1, Subtract<Num2, 1>, [...BuildArr<Num1, number>, ...ResultArr]>
type MutiplyResult = Mutiply<2,3>
// 减法
type Divide<Num1 extends number, Num2 extends number, CountArr extends unknown[] = []> = Num1 extends 0 ? CountArr['length'] : Divide<Subtract<Num1, Num2>, Num2, [unknown, ...CountArr]>
type DivideResult = Divide<9,3>

type StrLen<Str extends string, CountArr extends unknown[]= []> = Str extends `${infer F}${infer Rest}` ? StrLen<Rest, [...CountArr, unknown]> : CountArr['length']
type StrLenResult = StrLen<'abcdef'>

type GreaterThan<Num1 extends number, Num2 extends number, CountArr extends unknown[] = []> = Num1 extends Num2 ? false : CountArr['length'] extends Num2 ? true : CountArr['length'] extends Num1 ? false : GreaterThan<Num1, Num2, [...CountArr, unknown]>
type GreaterThanResult = GreaterThan<3, 3>

// 斐波那契数列
// 1 1 2 3 5 8 13 21 34 55 89
type FibonacciLoop<
  Num extends number,
  PrevArr extends unknown[] = [1],
  CurrentArr extends unknown[] = [],
  IndexArr extends unknown[] = []
> = IndexArr['length'] extends Num ?
  CurrentArr['length'] :
  FibonacciLoop<Num, CurrentArr, [...PrevArr, ...CurrentArr], [...IndexArr, unknown]>
type FibonacciLoopResult = FibonacciLoop<8>

上次更新: 2023/03/20, 16:56:52
最近更新
01
在js中实现响应式(原理参考solidjs)
03-21
02
使用VSCode插件快速导航代码库:类似autojump的跳转功能
03-20
03
react事件系统
11-07
更多文章>