类型编程的目的就是对各种类型进行转换生成需要的类型结果、首先我们要先学习下如何声明类型变量、 TS类型系统中支持三种声明类型的变量:type、infer、类型参数

Type

type叫类型别名、声明一个变量存储某个类型

  1. type g = Promise<number>; //g是一个promise、并且resolve的结果是一个number类型的值

type类型参数、定义接受一个P参数、使用extends判断P是否等于 字符串’a’、如果是则返回true 否者 false

  1. type g<P> = P extends 'a' ? true : false;
  2. type res = g<'a'> // true

infer用于类型的提取、后面跟着类型提取出来后储存的变量名称、相当于局部变量

  1. type GetValueType<P> = P extends Promise<infer Value> ? Value : never;


在提一句、TS里面不允许类型修改、如果想对类型做各种变换产生新的类型就需要重新构造

元组

  1. // 给tuple 添加一个类型
  2. type tuple = [1,2,3]; // 元组的重新构造
  3. type Push<Arr extends number[], Ele> = [...Arr, Ele]
  4. type PushRes = Push<tuple, 4> // type PushRes = [1, 2, 3, 4]
  5. // 合并两个元组
  6. type tuple1 = [1,2];
  7. type tuple2 = ['guang', 'fa'];
  8. // 得到 type tuple = [[1, 'guang'], [2, 'dong']];
  9. type mergeTule<One extends unknown[], Other extends unknown[]> =
  10. One extends [infer OneFirst, infer OneSecond]
  11. ? Other extends [infer OtherFirst, infer OtherSecond]
  12. ? [ [OneFirst, OtherFirst], [ OneSecond, OtherSecond]] : []
  13. : [];
  14. type mergeResult = mergeTule<tuple1, tuple2> // [[1, "guang"], [2, "fa"]]
  15. /*
  16. 现在是按个数进行写死的部分、如果动态个数的操作需要怎么写呢?答案是:递归
  17. */
  18. // 递归写法
  19. type recursionMerge<One extends unknown[], Other extends unknown[], Arr extends unknown[] = []> =
  20. One extends [infer OneFirst, ...infer OneRest]
  21. ? Other extends [ infer OtherFirst, ...infer OtherRest]
  22. ? recursionMerge<OneRest, OtherRest, [...Arr, [OneFirst, OtherFirst]]> : Arr
  23. : Arr;
  24. type mergeResult = recursionMerge<tuple1, tuple2>

字符串

  1. // 把传入的'huang'第一个字符串变成大写
  2. type CapitalizeStr<Str extends string> =
  3. Str extends `${infer First}${infer Rest}`
  4. ? `${Uppercase<First>}${Rest}` : Str;
  5. type res = CapitalizeStr<'huang'> // "Huang"
  6. // 我们完成一个guang_fa_huang => huangguangfa的修改
  7. type SubStr<Str extends string> =
  8. Str extends `${ infer Prefix}_${ infer content}_${infer Suffix}`
  9. ? `${Suffix}${Prefix}${content}` : Str;
  10. type res = SubStr<'guang_fa_huang'> // huangguangfa

函数

  1. // 添加一个函数参数
  2. type AppendArgumnet<Func extends Function, Arg> =
  3. Func extends (...args: infer Args) => infer ReturnType
  4. ? (...args:[...Args, Arg]) => ReturnType : never;
  5. // (args_0: string, args_1: "age") => void
  6. type res = AppendArgumnet<(name:string) => void, 'age'>

索引类型

  1. type obj = {
  2. name:'1',
  3. age:2,
  4. gender:true
  5. }
  6. type Mapping<Obj extends object> = {
  7. [Key in keyof Obj]: [Obj[Key], Obj[Key], Obj[Key]]
  8. }
  9. type res = Mapping<obj>
  10. // 除了对value做修改 也可以做Key做修改、通过 “as” 重映射的操作
  11. type UppercaseKey<Obj extends object> = {
  12. [Key in keyof Obj as Uppercase<Key & string>]: Obj[Key] //把string的key都变成大写
  13. }

总结

在TS不存在直接修改某个变量、都是通过重新构造的方式去创建新的类型、索引类型可以通过 as 重新映射类型