玩转TypeScript工具类型(中)

发表于 3年以前  | 总阅读数:351 次

本文是《玩转 TypeScript工具类型》系列的第二篇,包含了如下几部分内容

  • 必读:extends 条件运算符
  • Exclude<Type, ExcludeUnion>
  • Extract<Type, Union>
  • NonNullable
  • 必读:tuple type 元组类型
  • Parameters
  • ConstructorParameters
  • ReturnType
  • InstanceType

一、必读:extends条件运算符

ydtech

因为后续的源码中涉及到了 extends 关键字,所以需要先提前掌握这部分内容才能更好更容易的理解源码。可以参考[译]TypeScript条件类型,英语好的同学推荐直接看原文。

[译]TypeScript条件类型:https://juejin.cn/post/6985463429502877726

youdao

二、Exclude<T, E>:排除

ydtech

将 ExcludeUnion 联合类型的所有成员从 Type 中排除,可以理解为取差集。剩余的部分返回作为一个新类型。

2.1 源码解读

type Exclude<T, U> = T extends U ? never : T;

如何理解 T extends U ? never : T 呢?判断 T 中的每一项是否可以赋值给类型 U,如果可以,就返回 never,如果不可以,就返回当前这项。接下来我们结合一个具体的例子来理解一下这句话。

2.2 实战用法

// 排除一个具体的值

type T0 = Exclude<"a" | "b" | "c", "a"> // "b" | "c"

// 排除一种类型

type T1 = Exclude<string | number | (() => void), Function>

T0 为例,extends 关键字是如何发挥作用的呢?

type T0 = Exclude<"a" | "b" | "c", "a"> // "b" | "c"

// 等价于

type T0 = "a" extends "a" ? never : "a" 

  | "b" extends "a" ? never : "b"

  | "c" extends "a" ? never : "c"

// 等价于

type T0 = never | "b" | "c"

// 等价于

type T0 = "b" | "c"

如果无法理解这里的等价逻辑,建议阅读开头推荐的[译]TypeScript条件类型。

[译]TypeScript条件类型:https://juejin.cn/post/6985463429502877726

youdao

三、Extract<T, U>:提取

ydtech

选取 Type 类型和 Union 类型两者的公共部分并返回为一个新类型,可以理解为取交集

3.1 源码解析

/**

 * Extract from T those types that are assignable to U

 */

type Extract<T, U> = T extends U ? T : never;

提取出类型 T 中那些能赋值给类型 U 的类型。所以这里源码上和 Exclude 的区别就在于 never 放在了条件运算结果为 false 的分支上。所以如果理解了 Exclude,再理解 Extract 就不复杂了。

3.2 实战用法

// 提取一个具体的值

type T0 = Extract<"a" | "b" | "c", "a"> // "a" 

// 提取一种类型

type T1 = Extract<string | number | (() => void), Function>

这里就不再重复说明 extends 的处理逻辑了。

四、NonNullable

ydtech

过滤掉 Type 中的 null 和 undefined,剩余的类型作为一个新类型返回。其实就是 Exclude 的一种特殊情况

4.1 源码解析

type NonNullable<T> = T extends null | undefined ? never : T

可以发现和 Exclude<T, U> 的源码非常像,只是把 U 换成了 null | undefined。所以结合 Exclude<T, U> 还是很好理解的。

4.2 实战用法

type T0 = NonNullable<string | number | undefined>;

// type T0 = string | number

type T1 = NonNullable<string[] | null | undefined>;

// type T1 = string[]

五、必读:tuple type元组类型

ydtech

元组类型就是一个具有固定数量元素和元素类型都确定的数组类型。

Tuple types allow you to express an array with a fixed number of elements whose types are known, but need not be the same.

例如这就是一个元组类型:

let x: [string, number];

当我们访问已声明类型的元素时,可以获得正确的类型检查

// OK

console.log(x[0].substring(1));

// Property 'substring' does not exist on type 'number'.

console.log(x[1].substring(1));

当我们访问超出数组长度的下标时,获得的类型都是 undefined,并且会获得一个访问下标无可访问元素的错误提示

let x: [string, number];

x = ["hello", 10]; // OK

// Type '"world"' is not assignable to type 'undefined'.

// Tuple type '[string, number]' of length '2' has no element at index '3'.

x[3] = "world";

// Object is possibly 'undefined'.

// Tuple type '[string, number]' of length '2' has no element at index '5'.

console.log(x[5].toString());

六、Parameters

ydtech

基于一个函数参数的类型构造一个元组类型(tuple type)。所以这个工具类型的作用就是获取函数参数的类型。

6.1 源码解析

/**

 * Obtain the parameters of a function type in a tuple

 */

type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never;

源码中重点有两部分

  • T extends (...args: any) => any,规定了 T 必须是一个函数(any和never 除外),参数是 any 类型,所以参数可以是任意类型
  • T extends (...args: infer P) => any ? P : never,如果T是函数类型,那么这个 extends 走的就是 true 分支,也就是返回一个 P类型,而这个 P 类型就是参数 args 的类型。

如果对 infer 无法理解的同学可以再回顾一下[译]TypeScript条件类型

[译]TypeScript条件类型:https://juejin.cn/post/6985463429502877726

6.2 实战用法

declare function f1(arg: { a: number; b: string }): void;

type T0 = Parameters<() => string>;

// type T0 = []

type T1 = Parameters<(s: string) => void>;

// type T1 = [s: string]

type T2 = Parameters<<T>(arg: T) => T>;

// type T2 = [arg: unknown]

type T3 = Parameters<typeof f1>;

// type T3 = [arg: { a: number; b: string; }]

type T4 = Parameters<any>;

// type T4 = unknown[]

type T5 = Parameters<never>;

// type T5 = never

type T6 = Parameters<string>;

// Type 'string' does not satisfy the constraint '(...args: any) => any'.

type T7 = Parameters<Function>;

// Type 'Function' does not satisfy the constraint '(...args: any) => any'.

// Type 'Function' provides no match for the signature '(...args: any): any'.

这里需要关注一下 Parameters 传入 never 和 any 的情况,知道即可。

七、ConstructorParameters

ydtech

把构造函数的参数类型作为一个元组类型返回。我们已经知道如何获取一个函数的参数类型,即 [Parameters]

那么如果我们要获取构造函数的参数类型,那么首先先要判断出哪一个是构造函数,然后获取参数类型即可,思路是这么个思路,那么应该怎么实现呢?

7.1 源码解析

/**

 * Obtain the parameters of a constructor function type in a tuple

 */

type ConstructorParameters<T extends abstract new (...args: any) => any> = T extends abstract new (...args: infer P) => any ? P : never;

这里有两个需要关注的点:

  • abstract关键字修饰的函数叫抽象方法,而抽象方法只能出现在抽象类中
  • new (...args: any) => any,这就是对构造函数的定义

所以,ConstructorParameters 工具类型只是针对抽象类来发挥效果的,never 和 any 我们不需要关心。

7.2 实战用法

这里结合一个具体的例子,深入了解一下,就以 ErrorConstructor 为例:

interface ErrorConstructor {

  new(message?: string): Error;

  (message?: string): Error;

  readonly prototype: Error;

}

type T0 = ConstructorParameters<ErrorConstructor>;

这里 ConstructorParameters 是如何处理的呢?其实就是对 ErrorConstructor 的三条属性逐一代入 T extends abstract new (...args: infer P) => any ? P : never;,满足条件的就返回参数类型P

type T0 = string

八、ReturnType

ydtech

获取函数的返回值类型。结合我们在 [Parameters]获取函数参数类型的实现,可以很容易的自己实现出这个工具类型。

8.1 源码解析

/**

 * Obtain the return type of a function type

 */

type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;

和Parameters实现的唯一的区别就是infer的位置从参数位置跑到了返回值位置。这还是很好理解的。

注意返回值类型不是元组类型,因为在Parameters中,args是一个数组,所以返回的是一个元组类型,而函数的返回值可以是任意类型的。

8.2 实战用法

declare function f1(): { a: number; b: string };

type T0 = ReturnType<() => string>;

// type T0 = string

type T1 = ReturnType<(s: string) => void>;

// type T1 = void

type T2 = ReturnType<<T>() => T>;

// type T2 = unknown

type T3 = ReturnType<<T extends U, U extends number[]>() => T>;

// type T3 = number[]

type T4 = ReturnType<typeof f1>;

// type T4 = {a: number;b: string;}

type T5 = ReturnType<any>;

// type T5 = any

type T6 = ReturnType<never>;

// type T6 = never

type T7 = ReturnType<string>;

// 类型“string”不满足约束“(...args: any) => any”。ts(2344)

type T8 = ReturnType<Function>;

// 类型“Function”不满足约束“(...args: any) => any”。

// 类型“Function”提供的内容与签名“(...args: any): any”不匹配。ts(2344)

九、InstanceType

ydtech

获取构造函数实例的返回类型。也就是对构造函数调用 new 操作符后的返回值类型。我们已经知道了如何获取构造函数参数的类型,所以很方便的就可以推导出如何获取实例的类型。

9.1 源码解析

/**

 * Obtain the return type of a constructor function type

 */

type InstanceType<T extends abstract new (...args: any) => any> = T extends abstract new (...args: any) => infer R ? R : any;

9.2 实战用法

这里我们继续以 FunctionConstructor 为例:

interface FunctionConstructor {

  /**

   * Creates a new function.

   * @param args A list of arguments the function accepts.

   */

  new(...args: string[]): Function;

  (...args: string[]): Function;

  readonly prototype: Function;

}

type T0 = InstanceType<FunctionConstructor>;

结合 new(...args: string[]): Function; 可知:

type T0 = Function;

更多情况可以在 typescript playground 中自己尝试一下。

十、下回预告

ydtech

在下一篇《玩转TypeScript工具类型(下)》里,将会包括如下内容,敬请期待:

  • ThisParameterType
  • OmitThisParameter
  • ThisType

本文由哈喽比特于3年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/dq7KOAUQmpl0aDlkJSAP8A

 相关推荐

刘强东夫妇:“移民美国”传言被驳斥

京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。

发布于:1年以前  |  808次阅读  |  详细内容 »

博主曝三大运营商,将集体采购百万台华为Mate60系列

日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。

发布于:1年以前  |  770次阅读  |  详细内容 »

ASML CEO警告:出口管制不是可行做法,不要“逼迫中国大陆创新”

据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。

发布于:1年以前  |  756次阅读  |  详细内容 »

抖音中长视频App青桃更名抖音精选,字节再发力对抗B站

今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。

发布于:1年以前  |  648次阅读  |  详细内容 »

威马CDO:中国每百户家庭仅17户有车

日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。

发布于:1年以前  |  589次阅读  |  详细内容 »

研究发现维生素 C 等抗氧化剂会刺激癌症生长和转移

近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。

发布于:1年以前  |  449次阅读  |  详细内容 »

苹果据称正引入3D打印技术,用以生产智能手表的钢质底盘

据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。

发布于:1年以前  |  446次阅读  |  详细内容 »

千万级抖音网红秀才账号被封禁

9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...

发布于:1年以前  |  445次阅读  |  详细内容 »

亚马逊股东起诉公司和贝索斯,称其在购买卫星发射服务时忽视了 SpaceX

9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。

发布于:1年以前  |  444次阅读  |  详细内容 »

苹果上线AppsbyApple网站,以推广自家应用程序

据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。

发布于:1年以前  |  442次阅读  |  详细内容 »

特斯拉美国降价引发投资者不满:“这是短期麻醉剂”

特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。

发布于:1年以前  |  441次阅读  |  详细内容 »

光刻机巨头阿斯麦:拿到许可,继续对华出口

据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。

发布于:1年以前  |  437次阅读  |  详细内容 »

马斯克与库克首次隔空合作:为苹果提供卫星服务

近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。

发布于:1年以前  |  430次阅读  |  详细内容 »

𝕏(推特)调整隐私政策,可拿用户发布的信息训练 AI 模型

据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。

发布于:1年以前  |  428次阅读  |  详细内容 »

荣耀CEO谈华为手机回归:替老同事们高兴,对行业也是好事

9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI操控无人机能力超越人类冠军

《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI生成的蘑菇科普书存在可致命错误

近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。

发布于:1年以前  |  420次阅读  |  详细内容 »

社交媒体平台𝕏计划收集用户生物识别数据与工作教育经历

社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”

发布于:1年以前  |  411次阅读  |  详细内容 »

国产扫地机器人热销欧洲,国产割草机器人抢占欧洲草坪

2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。

发布于:1年以前  |  406次阅读  |  详细内容 »

罗永浩吐槽iPhone15和14不会有区别,除了序列号变了

罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。

发布于:1年以前  |  398次阅读  |  详细内容 »
 相关文章
Android插件化方案 5年以前  |  237229次阅读
vscode超好用的代码书签插件Bookmarks 2年以前  |  8063次阅读
 目录