「这是我参与11月更文挑战的第14天,活动详情查看:2021最后一次更文挑战」
TypeScript系列学习笔记:
TypeScript | 第一章:环境搭建及基础数据类型
TypeScript | 第二章:类、接口和之间的关系
TypeScript | 第三章:函数、泛型和枚举
TypeScript | 第四章:命名空间和模块
TypeScript | 第六章:理解声明合并,以及编写声明文件
TypeScript | 第七章:配置文件说明
1. 交叉类型
交叉类型是将多个类型合并为一个类型,用符号"&"表示。
// 交叉类型实现的方式 extend(Person,Loggable) == Person & Loggable
function extend<T, U>(first: T, second: U): T & U {
let result = <T & U>{};
for (let id in first) {
(<any>result)[id] = (<any>first)[id];
}
for (let id in second) {
if (!result.hasOwnProperty(id)) {
(<any>result)[id] = (<any>second)[id];
}
}
return result;
}
2. 联合类型
联合类型表示一个值可以是几种类型之一,用符号"|"分隔每个类型。
// 联合类型:padding若声明为any,编译能通过,但运行时会报错。
function padLeft(value: string, padding: string | number) {
if (typeof padding === "number") {
return Array(padding + 1).join(" ") + value;
}
if (typeof padding === "string") {
return padding + value;
}
throw new Error(`Expected string or number, got '${padding}'.`);
}
// 若值为联合类型,只能访问此联合类型的所有类型里共有的成员
interface Bird{
fly();
layEggs();
}
interface Fish{
swim();
layEggs();
}
function getPet():Bird|Fish{}
let pet = getPet();
pet.layEggs() // 正确,只能访问共有的成员
pet.swim() // 错误
3. 自动类型推断
1. typeof
TypeScript可以将typeof识别为一个类型保护,可以直接在代码里检查类型了。
let num:number|string = Math.random()>0.2?1:'1'
// 类型必须是:"number", "string", "boolean"或 "symbol"
if(typeof num ==='number'){ // 这里称为typeof类型保护
num+=1
}
2. instanceof
nstanceof类型保护是通过构造函数来细化类型的一种方式。
let num:number|string = Math.random()>0.2?new Number(1):new String('1')
if(num instanceof Number){ // 称为instanceof类型保护
num+=1
}
3. 浏览器API
document.onmousedown = e=>console.log(e) // 能自动推动出e为MouseEvent
4. 其他方式
let n = 1 ; //ts自动推断出n为number类型
let arr = [1] // 内部有数据,能推断出正确类型
arr.push(2) // 正确
arr.push('3') // 错误,参数是string类型
let arr2 = [] // 未声明类型,默认为any[]
arr2.push(1)
arr2.push('2')
4. null 和 undefined
默认情况,类型检查器认为null与undefined可以赋值给任何类型,它们是其它类型的一个有效值。
--strictNullChecks标记可以解决,声明变量时不会自动包含null或 undefined。可选参数会自动加上| undefined。
let s = "a";
s = null; // 错误,null 不能赋值给string
let sn:string|null = 'b'
sn = null; // 正常
5. 类型断言
告诉ts这是什么类型,它都信。
let obj = Math.random()>0.2?[]:1;
// 方式一:"<>" 表示
(<number[]>obj).push(1)
// 方式二:as表示
(obj as number[])obj.push(1)
6. 类型别名
类型别名会给一个类型起个新名字。 类型别名有时和接口很像,但是可以作用于原始值,联合类型,元组以及其它任何你需要手写的类型。
型别名可以表示很多接口表示不了的类型, 比如字面量类型(常用来校验取值范围)。
类型别名不能出现在声明右侧的任何地方。
type Color = 'red'|'yellow'|'green'
type Num = 1|2|3
type Name = '张三'|'李四'
let a:Color = 'black' // 报错,Color类型中没有black
interface A{a:number}
type B = A | {b:number}
type C = A & {c:number}
7. 索引类型
ts中的keyof和他类似, 可以用来获取对象类型的键值。
// T[K], 索引访问操作符
function getProperty<T, K extends keyof T>(o: T, name: K): T[K] {
return o[name]; // o[name] is of type T[K]
}
type A = keyof {a:1,b:2} // 'a'|'b'
type B = keyof [1,2] // '1'|'2'|'push'...,不仅获取内容,还获取到Array原型上的方法
8. 总结
至此完成了高级类型的学习,不完善的地方后续陆续补充。