知识点摘要

本节课主要关键词为: 自动类型推断 / 类型断言 / 类型别名(type) / 映射类型(Pick/Record等...) / 条件类型(extends) / 类型推断(infer)

自动类型推断(不用你标类型了,ts自己猜)

第二课我们讲了那么多基础类型, 大家现在写ts的时候一定会在每个变量后面都加上类型吧? 但是?

现在告诉大家有些情况下你不需要标注类型, ts可以根据你写的代码来自动推断出类型:

赋值字面量给变量

let n = 1; // ts会自动推断出n是number类型
n+=3 // 不报错,因为已知类型 let arr1 = []; // 类型为: any[]
arr1.push(1,2,{o:3}); let arr = [1]; // 内部要有数字, 才能推断出正确类型
arr.push(2);
自动阅读if条件判断
let n: number|null = 0.5 < Math.random() ? 1:null;
if(null !== n){
n+=3 // ts知道现在n不是null是number
}
浏览器自带api
document.ontouchstart = ev=>{ // 能自动推断出ev为TouchEvent
console.log(ev.touches); // 不报错, TouchEvent上有touches属性
}
typeof

typeof就是js中的typeof, ts会根据你代码中出现的typeof来自动推断类型:

let n:number|string = 0.5 < Math.random()? 1:'1';

// 如果没有typeof, n*=2会报错, 提示没法推断出当前是number类型, 不能进行乘法运算
if('number' === typeof n) {
n*= 2;
} else {
n= '2';
}

注意: 在ts文档中, 该部分的知识点叫做typeof类型保护, 和其他类型推断的内容是分开的, 被写在高级类型/类型保护章节中.

instanceof

ts会根据你代码中出现的instanceof来自动推断类型:

let obj = 0.5 < Math.random() ? new String(1) : new Array(1);
if(obj instanceof String){
// obj推断为String类型
obj+= '123'
} else {
// obj为any[]类型
obj.push(123);
}

注意: 在ts文档中, 该部分的知识点叫做instanceof类型保护, 和其他类型推断的内容是分开的, 被写在高级类型/类型保护章节中.

类型断言(你告诉ts是什么类型, 他都信)

有些情况下系统没办法自动推断出正确的类型, 就需要我们标记下, 断言有2种语法, 一种是通过"<>", 一种通过"as", 举例说明:

let obj = 0.5 < Math.random() ? 1 : [1]; // number|number[]

// 断言, 告诉ts, obj为数组
(<number[]>obj).push(1); //等价
(obj as number[]).push(1);

类型别名(type)

类型别名可以表示很多接口表示不了的类型, 比如字面量类型(常用来校验取值范围):

type A = 'top'|'right'|'bottom'|'left'; // 表示值可能是其中的任意一个
type B = 1|2|3;
type C = '红'|'绿'|'黄';
type D = 150; let a:A = 'none'; // 错误, A类型中没有'none'
更多组合:
interface A1{
a:number;
}
type B = A1 | {b:string};
type C = A1 & {b:string}; // 与泛型组合
type D<T> = A1 | T[];

索引类型(keyof)

js中的Object.keys大家肯定都用过, 获取对象的键值, ts中的keyof和他类似, 可以用来获取对象类型的键值:

type A = keyof {a:1,b:'123'} // 'a'|'b'
type B = keyof [1,2] // '1'|'2'|'push'... , 获取到内容的同时, 还得到了Array原型上的方法和属性(实战中暂时没遇到这种需求, 了解即可)

可以获得键值, 也可以获取对象类型的值的类型:

type C = A['a'] // 等于type C = 1;
let c:C = 2 // 错误, 值只能是1

映射类型(Readonly, Pick, Record等...)

映射类型比较像修改类型的工具函数, 比如Readonly可以把每个属性都变成只读:

type A  = {a:number, b:string}
type A1 = Readonly<A> // {readonly a: number;readonly b: string;}

打开node_modules/typescript/lib文件夹可以找到lib.es5.d.ts, 在这我们能找到Readonly的定义:

type Readonly<T> = {
readonly [P in keyof T]: T[P];
};

其实不是很复杂, 看了本节课前面前面的内容, 这个很好理解是吧:

  1. 定义一个支持泛型的类型别名, 传入类型参数T.
  2. 通过keyof获取T上的键值集合.
  3. in表示循环keyof获取的键值.
  4. 添加readonly标记.
Partial<T>, 让属性都变成可选的
type A  = {a:number, b:string}
type A1 = Partial<A> // { a?: number; b?: string;}
Required<T>, 让属性都变成必选
type A  = {a?:number, b?:string}
type A1 = Required<A> // { a: number; b: string;}
Pick<T,K>, 只保留自己选择的属性, U代表属性集合
type A  = {a:number, b:string}
type A1 = Pick<A, 'a'> // {a:number}
Omit<T,K> 实现排除已选的属性
type A  = {a:number, b:string}
type A1 = Omit<A, 'a'> // {b:string}
Record<K,T>, 创建一个类型,T代表键值的类型, U代表值的类型
type A1 = Record<string, string> // 等价{[k:string]:string}
Exclude<T,U>, 过滤T中和U相同(或兼容)的类型
type A  = {a:number, b:string}
type A1 = Exclude<number|string, string|number[]> // number // 兼容
type A2 = Exclude<number|string, any|number[]> // never , 因为any兼容number, 所以number被过滤掉
Extract<T,U>, 提取T中和U相同(或兼容)的类型
type A  = {a:number, b:string}
type A1 = Extract<number|string, string|number[]> // string
NonNullable<T>, 剔除T中的undefined和null
type A1 = NonNullable<number|string|null|undefined> // number|string
ReturnType<T>, 获取T的返回值的类型
type A1= ReturnType<()=>number> // number
InstanceType<T>, 返回T的实例类型

ts中类有2种类型, 静态部分的类型和实例的类型, 所以T如果是构造函数类型, 那么InstanceType可以返回他的实例类型:

interface A{
a:HTMLElement;
} interface AConstructor{
new():A;
} function create (AClass:AConstructor):InstanceType<AConstructor>{
return new AClass();
}
Parameters<T> 获取函数参数类型

返回类型为元祖, 元素顺序同参数顺序.

interface A{
(a:number, b:string):string[];
} type A1 = Parameters<A> // [number, string]
ConstructorParameters<T> 获取构造函数的参数类型

Parameters类似, 只是T这里是构造函数类型.

interface AConstructor{
new(a:number):string[];
} type A1 = ConstructorParameters<AConstructor> // [number]

extends(条件类型)

T extends U ? X : Y

用来表示类型是不确定的, 如果U的类型可以表示T, 那么返回X, 否则Y. 举几个例子:

type A =  string extends '123' ? string :'123' // '123'
type B = '123' extends string ? string :123 // string

明显string的范围更大, '123'可以被string表示, 反之不可.

infer(类型推断)

单词本身的意思是"推断", 实际表示在extends条件语句中声明待推断的类型变量. 我们上面介绍的映射类型中就有很多都是ts在lib.d.ts中实现的, 比如Parameters:

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

上面声明一个P用来表示...args可能的类型, 如果(...args: infer P)可以表示 T, 那么返回...args对应的类型, 也就是函数的参数类型, 反之返回never.

注意: 开始的T extends (...args: any) => any用来校验输入的T是否是函数, 如果不是ts会报错, 如果直接替换成T不会有报错, 会一直返回never.

应用infer

接下来我们利用infer来实现"删除元祖类型中第一个元素", 这常用于简化函数参数

export type Tail<Tuple extends any[]> = ((...args: Tuple) => void) extends ((a: any, ...args: infer T) => void) ? T : never;

为vue3.0学点typescript, 解读高级类型的更多相关文章

  1. TypeScript完全解读(26课时)_12.TypeScript完全解读-高级类型(1)

    12.TypeScript完全解读-高级类型(1) 高级类型中文网的地址:https://typescript.bootcss.com/advanced-types.html 创建新的测试文件 ind ...

  2. TypeScript完全解读(26课时)_13.TypeScript完全解读-高级类型(2)

    13.TypeScript完全解读-高级类型(2) 高级类型中文网的地址:https://typescript.bootcss.com/advanced-types.html 创建文件并在index. ...

  3. TypeScript入门-高级类型

    高级类型 交叉类型 交叉类型,就是将多个类型合并为一个新的类型,这个新的类型具有这多个类型的成员,含有这几个类型的所有特性,是他们的综合体,像是集合的并集 例子: function extend< ...

  4. TypeScript 素描 - 高级类型、迭代器

    /* 交叉类型,在TypeScrpt中是很特有的.所以值得认真学习 交叉类型是将多个类型合并为一个类型,这让我们可以把现有的多种类型叠加到一起成为一种 类型 交叉类型同时拥有 Person 和 Emp ...

  5. TypeScript 之 基础类型、高级类型

    基础类型:https://m.runoob.com/manual/gitbook/TypeScript/_book/doc/handbook/Basic%20Types.html 高级类型:https ...

  6. 预计2019年发布的Vue3.0到底有什么不一样的地方?

    摘要: Vue 3.0预览. 原文:预计今年发布的Vue3.0到底有什么不一样的地方? 作者:小肆 微信公众号:技术放肆聊 Fundebug经授权转载,版权归原作者所有. 还有几个月距离 vue2 的 ...

  7. TypeScript 高级类型

    ⒈交叉类型(Intersection Types) 交叉类型是将多个类型合并为一个类型. 这让我们可以把现有的多种类型叠加到一起成为一种类型,它包含了所需的所有类型的特性. 例如, Person &a ...

  8. Vue3.0新特性

    Vue3.0新特性 Vue3.0的设计目标可以概括为体积更小.速度更快.加强TypeScript支持.加强API设计一致性.提高自身可维护性.开放更多底层功能. 描述 从Vue2到Vue3在一些比较重 ...

  9. Python进阶:全面解读高级特性之切片!

    导读:切片系列文章连续写了三篇,本文是对它们做的汇总.为什么要把序列文章合并呢?在此说明一下,本文绝不是简单地将它们做了合并,主要是修正了一些严重的错误(如自定义序列切片的部分),还对行文结构与章节衔 ...

随机推荐

  1. c++11 原生字符串字面值

    c++11 原生字符串字面值 #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <string> #in ...

  2. 一次解决黑帽SEO的经历

    最近有个朋友跟我说他的网站被黑了,百度快照里显示的是另一个网站,如: 于是查找了些资料,终于找到了问题所在,记录如下: 关于黑帽SEO1.暗链:其实“暗链”就是看不见的网站链接,“暗链”在网站中的链接 ...

  3. caffe笔记

    1. 训练    cifar10 示例 ① cd caffe.1.0.0 ./data/cifar10/get_cifar10.sh    #获取图片 ② ./examples/cifar10/cre ...

  4. flutter问题集锦

    现在的多平台开发很多啦,目前主流的救赎react native 和weex了,其他的旧的就不说了,新出来的gomobile目前基本无人使用,底层的很多原生对接还没有完善,flutter发布了第一版正式 ...

  5. MySQL cmd操作

    1.开启关闭服务 net start mysql net stio mysql 2.登陆 在CMD命令窗口敲入命令 mysql -hlocalhost -uroot -p 后按回车(注意这里的&quo ...

  6. 第六章、ajax方法以及序列化组件

    目录 第六章.ajax方法 一.choice参数介绍 二.MTV与MVC模型 三.ajax方法 四.案例 五.Ajax传json格式的数据 六. AJAX传文件 代码如下 ajax传文件需要注意的事项 ...

  7. Computer Vision_2_Active Shape Models:Active Shape Models-Their Training and Application——1995

    此为计算机视觉部分,主要侧重在底层特征提取,视频分析,跟踪,目标检测和识别方面等方面. 1. Active Appearance Models 活动表观模型和活动轮廓模型基本思想来源 Snake,现在 ...

  8. Zabbix4.2Server端部署

    一.安装 1.前期安装准备 前期准备一个大一点的分区准备用于zabbix 数据库的存放,为方便后期扩容,我们在这里选择新加一个磁盘并以LVM的方式进行挂载(此处省略虚拟机添加硬盘等操作) # df - ...

  9. Prometheus(1) 概念

    Prometheus Prometheus是一套开源的监控&报警&时间序列数据库的组合.对我来说,它跟 zabbix 最大的区别就是它没有模板,所有的告警规则都得自己写... 它有一套 ...

  10. BZOJ2208 [Jsoi2010]连通数[缩点/Floyd传递闭包+bitset优化]

    显然并不能直接dfs,因为$m$会非常大,复杂度就是$O(mn)$: 这题有三种做法,都用到了bitset的优化.第二种算是一个意外的收获,之前没想到竟然还有这种神仙操作.. 方法一:缩点+DAG上b ...