深入理解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关键字内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Typescript 中的 interface 和 type 到底有什么区别详解

    interface VS type 大家使用 typescript 总会使用到 interface 和 type,官方规范 稍微说了下两者的区别 An interface can be named in an extends or implements clause, but a type alias for an object type literal cannot. An interface can have multiple merged declarations, but a type

  • 关于TypeScript模块导入的那些事

    前言 模块在其自身的作用域里执行,而不是在全局作用域里:这意味着定义在一个模块里的变量,函数,类等等在模块外部是不可见的,除非你明确地使用export之一导出它们. 相反,如果想使用其它模块导出的变量,函数,类,接口等的时候,你必须要导入它们,可以使用import之一. 模块是自声明的.在TypeScript里,两个模块之间的关系是通过在文件级别上使用import和export建立的. 下面话不多说了,来一起看看详细的介绍吧 ES6 模块导入的限制 我们先来看一个具体的例子: 在 Node 项目

  • TypeScript 中接口详解

    在 TypeScript 中,接口是用作约束作用的,在编译成 JavaScript 的时候,所有的接口都会被擦除掉,因为 JavaScript 中并没有接口这一概念. 先看看一个简单的例子: function printLabel(labelledObj: { label: string }) { console.log(labelledObj.label); } var myObj = { size: 10, label: "Size 10 Object" }; printLabel

  • TypeScript学习之强制类型的转换

    前言 使用强类型变量常常需要从一种类型向另一种类型转换,通常使用ToString或ParseInt可以来实现一些简单的转换,但是有时候需要像.NET语言中那样将一种类型显示的转换为另一种类型,在TypeScript规范中,被称为"类型断言",它仍然是类型转换,只是语法是有些不同.下面来详细看看TypeScript的强制类型转换. TypeScript强制类型转换 在 TypeScript 中将一个 number 转换成 string ,这样做会报错: var a:number = 12

  • TypeScript类型声明书写详解

    本文总结一下TypeScript类型声明的书写,很多时候写TypeScript不是问题,写类型就特别纠结,我总结下,我在使用TypeScript中遇到的问题.如果你遇到类型声明不会写的时候,多看看lodash的声明,因为lodash对数据进行各种变形操作,所以你能遇到的,都有参考示例. 基本类型 // 变量 const num: number = 1; const str: string = 'str'; const bool: boolean = true; const nulls: null

  • 关于TypeScript中import JSON的正确姿势详解

    前言 Typescript是微软内部出品的,用actionscript的语法在写js的一门新语言,最近 TypeScript 中毒,想想我一个弱类型出身的人,怎么就喜欢上了类型约束--当然这不是重点,重点可能还是 JS 没有接口,我没法靠 class 语法糖写的非常 OO--下面这篇文章想说的其实是在 ts 中如何正确的 import json 格式. 首先我使用了基本姿势 import * as variable from './fooooooo.json' 结果发现他提示我并没有这个 mod

  • 在 Typescript 中使用可被复用的 Vue Mixin功能

    转到用 Typescript 写 Vue 应用以后,经过一轮工具链和依赖的洗礼,总算蹒跚地能走起来了,不过有一个很常用的功能 mixin,似乎还没有官方的解决方案. 既想享受 mixin 的灵活和方便,又想收获 ts 的类型系统带来的安全保障和开发时使用 IntelliSense 的顺滑体验. vuejs 官方组织里有一个 'vue-class-component' 以及连带推荐的 'vue-property-decorator',都没有相应实现.翻了下前者的 issue,有一条挂了好些时间的待

  • Typescript的三种运行方式(小结)

    一.在线complier 这种方式最简单,不需在本地做任何配置安装,只需进入Typescript的官网,点击里面的playground就可以直接写代码了.但这种方式只适用于测试而不适用于开发. 二.本地命令行编译 1.在本地编译运行Typescript需要使用npm下载typescript npm install -g typescript 至于npm,就是node的包管理工具,下载node后就自动带了. 2.下载完成后可以使用 tsc -v 查看版本 3.使用:如在本地创建Hello.ts e

  • 深入理解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

  • 深入理解Java中的final关键字_动力节点Java学院整理

    Java中的final关键字非常重要,它可以应用于类.方法以及变量.这篇文章中我将带你看看什么是final关键字?将变量,方法和类声明为final代表了什么?使用final的好处是什么?最后也有一些使用final关键字的实例.final经常和static一起使用来声明常量,你也会看到final是如何改善应用性能的. final关键字的含义? final在Java中是一个保留的关键字,可以声明成员变量.方法.类以及本地变量.一旦你将引用声明作final,你将不能改变这个引用了,编译器会检查代码,如

  • 理解javascript中的with关键字

    说起js中的with关键字,很多小伙伴们的第一印象可能就是with关键字的作用在于改变作用域,然后最关键的一点是不推荐使用with关键字.听到不推荐with关键字后,我们很多人都会忽略掉with关键字,认为不要去管它用它就可以了.但是有时候,我们在看一些代码或者面试题的时候,其中会有with关键字的相关问题,很多坑是你没接触过的,所以还是有必要说说with这一个关键字. 一.基本说明 在js高级程序设计中是这样描述with关键字的:with语句的作用是将代码的作用域设置到一个特定的作用域中,基本

  • 深入理解java中的synchronized关键字

    synchronized 关键字,代表这个方法加锁,相当于不管哪一个线程A每次运行到这个方法时,都要检查有没有其它正在用这个方法的线程B(或者C D等),有的话要等正在使用这个方法的线程B(或者C D)运行完这个方法后再运行此线程A,没有的话,直接运行它包括两种用法:synchronized 方法和 synchronized 块. 1. synchronized 方法:通过在方法声明中加入 synchronized关键字来声明 synchronized 方法.如: 复制代码 代码如下: publ

  • 深入理解Java中的volatile关键字(总结篇)

    基本概念 -------------------------------------------------------------------------------- 先补充一下概念:Java 内存模型中的可见性.原子性和有序性. 可见性: 可见性是一种复杂的属性,因为可见性中的错误总是会违背我们的直觉.通常,我们无法确保执行读操作的线程能适时地看到其他线程写入的值,有时甚至是根本不可能的事情.为了确保多个线程之间对内存写入操作的可见性,必须使用同步机制. 可见性,是指线程之间的可见性,一个

  • 彻底理解Python中的yield关键字

    阅读别人的python源码时碰到了这个yield这个关键字,各种搜索终于搞懂了,在此做一下总结: 通常的for...in...循环中,in后面是一个数组,这个数组就是一个可迭代对象,类似的还有链表,字符串,文件.它可以是mylist = [1, 2, 3],也可以是mylist = [x*x for x in range(3)].它的缺陷是所有数据都在内存中,如果有海量数据的话将会非常耗内存. 生成器是可以迭代的,但只可以读取它一次.因为用的时候才生成.比如 mygenerator = (x*x

  • 深入理解Javascript中的this关键字

    自从接触javascript以来,对this参数的理解一直是模棱两可.虽有过深入去理解,但却也总感觉是那种浮于表面,没有完全理清头绪. 但对于this参数,确实会让人产生很多误解.那么this参数到底是何方神圣? 理解this this是一个与执行上下文(execution context,也就是作用域)相关的特殊对象.因此,它可以叫作上下文对象(也就是用来指明执行上下文是在哪个上下 文中被触发的对象). 任何对象都可以做为上下文中的this的值.在一些对ECMAScript执行上下文和部分th

  • 深入理解Swift中的访问控制关键字

    前言 在Swift3.0以前有三种访问控制关键字,分别是private.internal和public.而在swift3以后,又在原来的基础上增加了两种访问控制关键字:fileprivate和open.他们可以看作是private和public的进一步细分.下面是各个修饰符的区别以及访问权限排序. 各个修饰符的区别 private swift3.0 private访问级别所修饰的属性或者方法只能在当前类里访问. class A { private func test() { print("thi

  • 深入理解C++中常见的关键字含义

    1. inline:定义内联函数,该关键字是基于定义,如果只在函数声明时给出inline,则函数不会被认为是内联函数,所以必须在函数定义的地方也加上inline,同时inline只是向编译器建议函数以内联函数处理,不是强制的.2. const:定义常成员,包括const数据成员和const成员函数,const数据成员必须,也只能通过构造函数的初始化列表进行初始化,const成员函数只能访问类的成员,不能进行修改,如果需要修改,则引入下面的mutable关键字.3.mutable:这个关键字的引入

  • 简单了解TypeScript中如何继承 Error 类

    前言 在JavaScript 中很多时候都需要自定义错误,尤其是开发 Node.js 应用的时候. 比如一个典型的网站服务器可能需要有 NetworkError, DatabaseError, UnauthorizedError 等. 我们希望这些类都拥有 Error 的特性:有错误消息.有调用栈.有方便打印的 toString 等. 最直观的实现方式便是 继承 Error 类. 但考虑 TypeScript 需要编译到 ES5 兼容性问题会较为复杂, 本文用来帮助理解 TypeScript 中

随机推荐