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是什 ...
随机推荐
- 操作系统中的进程同步与Window中利用内核对象进行线程同步的关系
操作系统中为了解决进程间同步问题提出了用信号量机制,信号量可分为四种类型分别是互斥型信号量,记录型信号量,AND型信号量,信号量集. 互斥型信号量 互斥型信号量是资源数量为1的特殊的记录型信号量.表示 ...
- 2021年主流CRM系统盘点
面对市面上五花八门的CRM系统,相信您在选择的时候肯定是一头雾水.哪个CRM系统功能最强大?哪个CRM系统性价比最高?哪个CRM系统最适合企业使用?本篇文章小编将选出几家有代表性的CRM系统,并进行对 ...
- c语言常见编译问题
1 . warn.c:6:2: warning: implicit declaration of function 'strcpy' [-Wimplicit-function-declaration] ...
- Mybatis-plus在原有的select查询语句中动态追加查询条件
一.适用场景 1.使用了xml形式的mapper.2.不想在select查询中大量使用<if>标签来判断条件是否存在而加入条件. 二.步骤 1.自定义wrapper继承QueryWrapp ...
- flink操作mysql
Flink读写mysql 如果是mvn项目的话,需要预先导入相应的包: <dependency> <groupId>org.apache.flink</groupId&g ...
- python上下文管理协议,即with的详细使用
一.with obj as f: #代码块... 二.执行流程: 1.with obj --->触发obj.__enter__(),需要在obj里写__enter__(self),在它里边写返回 ...
- stress工具使用指南和结果分析(好好好测试通过)
stress工具使用指南和结果分析 佛心看世界关注 0.1152019.05.13 09:17:35字数 547阅读 1,112 #stress `stress' imposes certain ty ...
- shell 读取某个目录下的所有文件
#!/bin/shFILE_PATH="xxx" xxx:路径cd $FILE_PATHfor FILE in `ls` do echo $FILE done
- linux基础之基础命令一
本节内容: 1. ls:列出当前目录下的文件和目录 -l: 长输出,显示文件的详细信息(-普通文本,d目录) -a: 显示所有文件,包括隐藏文件 -h: 人类易读(-lh) -d: 显示目录信息(-l ...
- 关于Python闭包的一切
任何把函数当做一等对象的语言,它的设计者都要面对一个问题:作为一等对象的函数在某个作用域中定义,但是可能会在其他作用域中调用,如何处理自由变量? 自由变量(free variable),未在局部作用域 ...