• TS进阶之infer


    前一篇文章我们有介绍条件类型,这篇文章我们来介绍下非常实用的infer的使用方法。

    使用介绍

    我们上篇文章中介绍了条件类型的基本语法是:

     T extends U ? X : Y; 
    
    • 1

    如果占位符类型U是一个可以被分解成几个部分的类型,譬如数组类型,元组类型,函数类型,字符串字面量类型等。这时候可以通过infer来获取U类型中某个部分的类型。

    infer语法的限制如下:

    1.infer只能在条件类型的 extends 子句中使用
    2.infer得到的类型只能在true语句中使用, 即X中使用

    推断数组(或者元组)的类型
    使用方法
    type InferArray = T extends (infer U)[] ? U : never; 
    
    • 1

    (infer U)和平时常写的string[]number[]等等是不是很像?这里就是通过(infer U)来获取数组对应的类型。

    案例
    type I0 = InferArray<[number, string]>; // string | number
    type I1 = InferArray; // string
    type I2 = InferArray; // number 
    
    • 1
    • 2
    • 3
    推断数组(或者元组)第一个元素的类型
    使用方法
    type InferFirst = T extends [infer P, ...infer _] ? P : never 
    
    • 1

    [infer P, ... infer _]infer P获取的是第一个元素的类型,而...infer _获取的是数组其他剩余元素的数组类型; 特别说明下,我们例子汇总不需要使用其他元素的类型,所以用_

    案例
    type I3 = InferFirst<[3, 2, 1]>; // 3 
    
    • 1
    推断数组(或者元组)最后一个元素的类型
    使用方法
    type InferLast = T extends [... infer _, infer Last] ? Last : never; 
    
    • 1

    这个和推断数组第一个元素的类型类似,...infer _获取的是最后一个元素之前的所有元素类型,infer Last获取的是最后一个元素的类型。

    案例
    type I4 = InferLast<[3, 2, 1]>; // 1 
    
    • 1
    推断函数类型的参数
    使用方法
    type InferParameters = T extends (...args: infer R) => any ? R : never; 
    
    • 1

    ...args 代表的是函数参数组成的元组, infer R代表的就是推断出来的这个函数参数组成的元组的类型。

    案例
    type I5 = InferParameters<((arg1: string, arg2: number) => void)>; // [string, number] 
    
    • 1
    推断函数类型的返回值
    使用方法
    type InferReturnType = T extends (...args: any) => infer R ? R : never; 
    
    • 1

    和前面的推断函数类型的参数类似,=> 后面的infer R代表的就是推断出来的函数的返回值类型。

    案例
    type I6 = InferReturnType<() => string>; // string 
    
    • 1
    推断Promise成功值的类型
    使用方法
    type InferPromise =T extends Promise ? U : never; 
    
    • 1
    案例
    type I7 = InferPromise>; // string 
    
    • 1
    推断字符串字面量类型的第一个字符对应的字面量类型
    使用方法
    type InferString = T extends `${infer First}${infer _}` ? First : []; 
    
    • 1
    案例
    type I8 = InferString<"Johnny">; // J 
    
    • 1
    综合案例

    接下来我举一些综合性的例子,我不介绍这些例子实现的功能,大家来感受下infer的使用技巧,看看是否能一眼看出来实现的功能:

    type Shift = T extends [infer L, ...infer R]? [...R] : []; 
    
    • 1
    type Pop = T extends [...infer L, infer R] ? [...L] : []; 
    
    • 1
    type Reverse = [] extends T? U: T extends [infer L, ...infer R]? Reverse: U; 
    
    • 1
    type FlipArguments = T extends (...arg: infer R) => infer S ? (...arg : Reverse<[...R]>) => S : T; 
    
    • 1
    type StartsWith = T extends `${U}${infer R}` ? true : false; 
    
    • 1
    type TrimLeft = S extends `${infer L}${infer R}`? L extends ' ' | '\n' | '\t'? TrimLeft: S: ''; 
    
    • 1
    type Trim = S extends `${' ' | '\t' | '\n'}${infer R}`? Trim: S extends `${infer L}${' ' | '\t' | '\n'}`? Trim: S; 
    
    • 1
    type StringToUnion = T extends ''? U: T extends `${infer L}${infer R}`? StringToUnion: U; 
    
    • 1

    这些例子中涉及到两个没有介绍的知识点:模版字面量类型递归类型,如果对这两个知识点不太懂的可以参考其他文章。这两个知识点我后面也会介绍。

  • 相关阅读:
    手把手带你开发你的第一个前端脚手架
    外贸建站教程步骤有哪些?独立站怎么搭建?
    python最优化算法实战---线性规划之内点法
    [sciter]:sciter如何使用i18实现桌面应用多语言切换及其利弊
    软件系统等保方案,市政项目,投标项目必须
    svg VS canvas,哪种在移动端适配度更好?实战经历告诉你~
    Eginx配置(SSL,令牌登录认证,IP白名单,代理转发)
    微信小程序中的列表渲染
    java档案类
    数据库的基本概念和常见的数据库软件介绍
  • 原文地址:https://blog.csdn.net/web220507/article/details/126399853