zoukankan      html  css  js  c++  java
  • 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>
    
    

    参考

  • 相关阅读:
    Azure PowerShell (7) 使用CSV文件批量设置Virtual Machine Endpoint
    Windows Azure Cloud Service (39) 如何将现有Web应用迁移到Azure PaaS平台
    Azure China (7) 使用WebMetrix将Web Site发布至Azure China
    Microsoft Azure News(4) Azure新D系列虚拟机上线
    Windows Azure Cloud Service (38) 微软IaaS与PaaS比较
    Windows Azure Cloud Service (37) 浅谈Cloud Service
    Azure PowerShell (6) 设置单个Virtual Machine Endpoint
    Azure PowerShell (5) 使用Azure PowerShell创建简单的Azure虚拟机和Linux虚拟机
    功能代码(1)---通过Jquery来处理复选框
    案例1.用Ajax实现用户名的校验
  • 原文地址:https://www.cnblogs.com/EnSnail/p/14938799.html
Copyright © 2011-2022 走看看