TS中的高级类型:
- 交叉类型
- 联合类型
- 类型保护
- null和undefined
- 类型别名
- 可辨识联合
一 交叉类型
交叉类型(&):用于组合多个类型为一个类型,常用于对象类型
interface Employee {
employeeID: number;
age: number;
}
interface Manager {
stockPlan: boolean;
}
type ManagementEmployee = Employee & Manager;
let newManager: ManagementEmployee = {
employeeID: 12345,
age: 34,
stockPlan: true
};
const mergeFunc = <T, U>(arg1: T, arg2: U): T & U => {
return Object.assign(arg1, arg2)
}
console.log(mergeFunc({
a:'aaa'},{
b:'bbb'})) //{a: 'aaa', b: 'bbb'}
二 联合类型
联合类型使用|分隔每种类型
let multiType: number | boolean;
multiType = 20; //* Valid
multiType = true; //* Valid
multiType = "twenty"; //* Invalid
三 类型保护
1.类型断言as
interface Bird {
fly: boolean;
sing: () => {
};
}
interface Dog {
fly: boolean;
bark: () => {
};
}
//用类型断言的方式进行类型保护
function trainAnmial(animal: Dog | Bird) {
if (animal.fly) {
(animal as Bird).sing();
} else {
(animal as Dog).bark();
}
}
2.typeof实现类型保护
function add(first: string | number, second: string | number) {
if (typeof first === 'string' || typeof second === 'string') {
return `${
first}${
second}`;
}
return first + second;
}
注意:如果使用typeof来实现类型保护, 那么只能保护number/string/boolean/symbol类型,不能用于null,同时也不能用于interface和type定义的类型,因为这些类型在运行时就不在了。
3.instanceof实现类型保护
instanceof用于校验类,类的类型信息会在运行时保留。
class A {
name:string = "1"
}
class C {
name1:string ="222"
}
function AM(param:A |C) {
if(param instanceof A){
//可以使用A的属性和方法
}
if(param instanceof C){
//可以使用C的属性和方法
}
}
4.in语法实现类型保护
in操作符对对象上的属性是否存在进行安全检查。
interface Dog {
name: string
bark: () => void
}
interface Bird {
name: string
fly: () => void
}
function doSomething(args: Dog | Bird) {
if ('bark' in args) {
args.bark()
} else {
args.fly()
}
}
5.=== 和 !==
使用===和!==判断字面量类型
type CheckState = 'yes' | 'no' | 'unknown'
function doSomething(args: CheckState) {
if (args === 'yes') {
console.log('check state is yes')
} else if (args === 'no') {
console.log('check state is no')
} else {
console.log('unknown check state')
}
}
四 null和undefined
null和undefined默认情况下是所有类型的子类型,即可以赋值给任意类型。但是如果在tsconfig.js中设置strictNullChecks为true时,就不能赋值给除它们自身以及void之外的类型了。想要使用可以配合联合类型来实现,如:
let s2: string | null = 'hi'
如果设置了"strictNullChecks": true,可选参数会被自动加上 |undefined,如果想要去除的话可以使用以下几种方法:
1.可选链(?.)
interface User {
name: string
address?: {
street: string
}
}
function printStreet(user: User) {
const streetInfo = user.address?.street
if (streetInfo === undefined) {
console.log('No street info')
} else {
console.log(streetInfo)
}
}
let user: User = {
name: 'O.O'
}
printStreet(user) // 'No street info'
2.空值合并(??)
它允许编写在处理null或undefined时有回退的表达式。
function printName(name: string | null | undefined) {
console.log(`${
name ?? '无名氏'}`)
}
printName(null) // '无名氏'
printName('O.O') // 'O.O'
3.空断言(!)
有时候忽略一个值为 null 或 undefined 的可能性是有意义的。一个简单的方法就是使用类型转换,但是 TypeScript 也提供了 ! 运算符作为方便的快捷方式。
function getValue(): string | undefined {
return 'hello'
}
let value = getValue()
value.length // value 可能为 undefined
// 使用 ! 运算符
value!.length // 5
五 type类型别名
type stringType = string
let str:stringType = 'abc'
type PositionType<T> = {
x:T, y:T}
const position1: PositionType<number> = {
x: 1,
y: 2
}
const position2: PositionType<string> = {
x: 'left',
y: 'top'
}
type Childs<T> = {
current: T,
child?: Childs<T>
}
const children:Childs<string> = {
current: 'first',
child: {
current: 'second',
child: {
current: 'third'
}
}
}
//可辨识联合
interface Square {
kind:'square',
size: number
}
interface Rectangle {
kind:'rectangle',
height:number,
width:number
}
interface Circle {
kind: 'circle',
radius: number
}
type Shape = Square | Rectangle | Circle
function assertNever(value: never):never {
throw new Error('unexpected error: ' + value)
}
function getArea(s: Shape):number{
switch(s.kind){
case 'square': return s.size * s.size;break;
case 'rectangle': return s.width * s.height;break;
case 'circle': return Math.PI * s.radius ** 2;break; // **是平方
default: return assertNever(s) // 处理一些异常情况
}
}
//这个例子通过统一的kind变量判断类型