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 关键字的理解的更多相关文章
- TypeScript 中命名空间与模块的理解?区别?
一.模块 TypeScript 与ECMAScript 2015 一样,任何包含顶级 import 或者 export 的文件都被当成一个模块 相反地,如果一个文件不带有顶级的import或者expo ...
- java中对final关键字的理解以及使用场景
谈到final关键字,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final关键字.另外,Java中的String类就是一个final类,那么今天我们就来了解final这个关键字的用法.
- c++中的const关键字的理解
看effective c++第二版推荐使用const,少用define.今天才发现发现这远远不够. #define定义的常量在预处理替换,debug的时候无法打印宏的,这种常量设置是有缺陷的, con ...
- 白话typescript中的【extends】和【infer】(含vue3的UnwrapRef)
大家好,我是小雨小雨,致力于分享有趣的.实用的技术文章. 内容分为翻译和原创,如果有问题,欢迎随时评论或私信,希望和大家一起进步. 分享不易,希望能够得到大家的支持和关注. extends types ...
- TypeScript `infer` 关键字
考察如下类型: type PromiseType<T> = (args: any[]) => Promise<T>; 那么对于符合上面类型的一个方法,如何得知其 Prom ...
- 正确理解JavaScript中的this关键字
JavaScript有this关键字,this跟JavaScript的执行上下文密切相关,很多前端开发工程师至今对this关键字还是模棱两可,本文将结合代码讲解下JavaScript的this关键字. ...
- 深入理解java中的synchronized关键字
synchronized 关键字,代表这个方法加锁,相当于不管哪一个线程A每次运行到这个方法时,都要检查有没有其它正在用这个方法的线程B(或者C D等),有的话要等正在使用这个方法的线程B(或者C D ...
- 转载 深入理解JavaScript中的this关键字
转载原地址: http://www.cnblogs.com/rainman/archive/2009/05/03/1448392.html 深入理解JavaScript中的this关键字 1. 一 ...
- 深入理解python中的yield关键字
想必大家都看过这样的代码: 上面的这段代码会计算0-9的平方并打印出来. 那么问题来了,这段代码和我们要说的东西有什么区别呢? 这里的关键字,yield,我在前面的文章里已经发过了.那么yield是什 ...
随机推荐
- 关于flask的模板注入的学习
flask模板注入的学习 关于flask模版注入,之前不太理解,看了很多文章才弄懂,主要原理就是渲染函数的参数用户可控就造成了模板注入 就会使用户构造恶意的代码进行逃逸从而进行攻击 flask模板渲染 ...
- 使用 Yarn workspace,TypeScript,esbuild,React 和 Express 构建 K8S 云原生应用(一)
本文将指导您使用 K8S ,Docker,Yarn workspace ,TypeScript,esbuild,Express 和 React 来设置构建一个基本的云原生 Web 应用程序. 在本教程 ...
- Spring Cloud 升级之路 - 2020.0.x - 5. 理解 NamedContextFactory
spring-cloud-commons 中参考了 spring-cloud-netflix 的设计,引入了 NamedContextFactory 机制,一般用于对于不同微服务的客户端模块使用不同的 ...
- [bug] Importing maven project 卡在%9不动
参考 Importing maven project 卡在%9不动 https://blog.csdn.net/weixin_43197380/article/details/89220337
- python发送钉钉消息
import requests import time import hashlib import hmac import base64 import re def SendMessage(messa ...
- 二进制部署K8S-3核心插件部署
二进制部署K8S-3核心插件部署 5.1. CNI网络插件 kubernetes设计了网络模型,但是pod之间通信的具体实现交给了CNI往插件.常用的CNI网络插件有:Flannel .Calico. ...
- fdisk 磁盘分区命令
fdisk fdisk磁盘分区命令 -v 打印 fdisk 的版本信息并退出.-l 列出指定设备的分区表信息并退出. 如果没有给出设备,那么使用那些在 /proc/partitions ( ...
- 提高IO输出速度
用DMA内存到内存的模式,直接把Gpio_data的数据循环的搬到GPIOC的BSRR寄存器上来控制GPIOC上电平的翻转,这样使得GPIO的速度达到了最快,输出70ns的脉宽,这已经是达到了DMA总 ...
- lua table的遍历
--ordered table iterator sorted by key function pairsByKeys(t) local a = {} for n in pairs(t) do a[# ...
- python3操作Kafka
# -- coding: UTF-8 import datetime import json import time from kafka import KafkaProducer producer= ...