您的位置:首页 > 编程学习 > > 正文

typescript使用技巧(深入理解typescript中的infer关键字的使用)

更多 时间:2021-10-21 08:43:08 类别:编程学习 浏览量:1270

typescript使用技巧

深入理解typescript中的infer关键字的使用

infer 这个关键字,整理记录一下,避免后面忘记了。有点难以理解呢。

infer

infer 是在 typescript 2.8中新增的关键字。

infer 可以在 extends 条件类型的字句中,在真实分支中引用此推断类型变量,推断待推断的类型。

例如:用infer推断函数的返回值类型

  • type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;
    
    type fn = () => number
    type fnReturnType = ReturnType<fn> // number
    
    
    
  • 在这个例子中,

    T extends U ? X : Y的形式为条件类型。

    infer R代表待推断的返回值类型,如果T是一个函数(...args: any[]) => infer R,则返回函数的返回值R,否则返回any

    案例:加深理解

    反解 Promise

  • // promise 响应类型
    type PromiseResType<T> = T extends Promise<infer R> ? R : T
    
    // 验证
    async function strPromise() {
      return 'string promise'
    }
    
    interface Person {
      name: string;
      age: number;
    }
    async function personPromise() {
      return {
        name: 'p',
        age: 12
      } as Person
    }
    
    type StrPromise = ReturnType<typeof strPromise> // Promise<string>
    // 反解
    type StrPromiseRes = PromiseResType<StrPromise> // str
    
    type PersonPromise = ReturnType<typeof personPromise> // Promise<Person>
    // 反解
    type PersonPromiseRes = PromiseResType<PersonPromise> // Person
    
    
  • 反解函数入参类型

  • type Fn<A extends any[]> = (...args: A) => any
    type FnArgs<T> = T extends Fn<infer A> ? A : any
    
    function strFn (name: string) {
    
    }
    
    type StrFn = FnArgs<typeof strFn> // [string]
    
    
  • tuple 转 union ,如:[string, number] -> string | number

  • type ElementOf<T> = T extends Array<infer E> ? E : never
    
    type TTuple = [string, number];
    
    type ToUnion = ElementOf<ATuple>; // string | number
    
    
    
  • new 操作符

  • // 获取参数类型
    type ConstructorParameters<T extends new (...args: any[]) => any> = T extends new (...args: infer P) => any ? P : never;
    
    // 获取实例类型
    type InstanceType<T extends new (...args: any[]) => any> = T extends new (...args: any[]) => infer R ? R : any;
    
    class TestClass {
    
      constructor(
        public name: string,
        public string: number
      ) {}
    }
    
    type Params = ConstructorParameters<typeof TestClass>;  // [string, numbder]
    
    type Instance = InstanceType<typeof TestClass>;         // TestClass
    
    
    
  • react - reducer

  • // 定义
    function useReducer<R extends Reducer<any, any>, I>(
      reducer: R,
      // ReducerState 推断类型
      initializerArg: I & ReducerState<R>,
      initializer: (arg: I & ReducerState<R>) => ReducerState<R>
    ): [ReducerState<R>, Dispatch<ReducerAction<R>>];
    
    // infer推断
    type ReducerState<R extends Reducer<any, any>> = R extends Reducer<infer S, any>
      ? S
      : never;
    // Reducer类型
    type Reducer<S, A> = (prevState: S, action: A) => S;
    
    
    // 使用 reducer
    const reducer = (x: number) => x + 1;
    const [state, dispatch] = useReducer(reducer, '');
    // Argument of type "" is not assignable to parameter of type 'number'.
    
    
    
  • vue3 - ref

  • export interface Ref<T = any> {
      [isRefSymbol]: true
      value: T
    }
    
    export function ref<T>(value: T): T extends Ref ? T : Ref<UnwrapRef<T>>
    
    export type UnwrapRef<T> = {
      cRef: T extends ComputedRef<infer V> ? UnwrapRef<V> : T
      ref: T extends Ref<infer V> ? UnwrapRef<V> : T
      array: T
      object: { [K in keyof T]: UnwrapRef<T[K]> }
    }[T extends ComputedRef<any>
      ? 'cRef'
      : T extends Array<any>
        ? 'array'
        : T extends Ref | Function | CollectionTypes | BaseTypes
          ? 'ref' // bail out on types that shouldn't be unwrapped
          : T extends object ? 'object' : 'ref']
    
    
    // 使用
    const count = ref({
      foo: ref('1'),
      bar: ref(2)
    })
    
    // 推断出
    const count: Ref<{
      foo: string;
      bar: number;
    }>
    
    const count = ref(2) // Ref<number>
    
    const count = ref(ref(2)) // Ref<number>
    
    
  • 参考

    理解TypeScript中的infer关键字

    Vue3 跟着尤雨溪学 TypeScript 之 Ref 类型从零实现

    巧用 TypeScript(五)---- infer

    到此这篇关于深入理解typescript中的infer关键字的使用的文章就介绍到这了,更多相关typescript infer关键字内容请搜索开心学习网以前的文章或继续浏览下面的相关文章希望大家以后多多支持开心学习网!