交叉类型
将多个类型合并为一个类型,可以用于对象混入。使用&符号连接
interface DogInterface{
run():void
}
interface CatInterface{
jump():void
}
let pet:DogInterface & CatInterface={
run(){},
jump(){}
}
交叉类型具有每一个类型的方法和属性
联合类型
联合类型可以对一个变量声明多个类型,但只能选择其中一种,使用 | 分隔各个类型
let name :string|number="Mr.Lee" //这表示name可以是string类型或者是number类型的值
class Dog implements DogInterface{
run(){}
eat(){}
}
class Cat implements CatInterface{
jump(){}
eat(){}
}
enum Master {Boy,Girl}
function getPet(master:Master){
let pet = master === Master.Boy?new Dog():new Cat()
pet.eat()
return pet
}
联合类型的变量只能访问两种类型共有的属性
可区分的联合类型
一个变量如果是多个类型的联合类型,并且具有共有属性,那么就可以用共有属性创建不同的类型保护区块
interface Square{
kind:"square"
size:number
}
interface Rectangle{
kind:"rectangle"
width:number
height:number
}
interface Circle{
kind:"circle"
r:number
}
type Shape=Square|Rectangle|Circle
function area(s:Shape){
switch(s.kind){
case "square":
return s.size=s.size;
break;
case "rectangle":
return s.height=s.width;
break;
case "circle":
return Math.PI*s.r**2
default :
return ((e:never)=>{throw new Error(e)})(s)//该函数的作用为判断s的类型是否为never类型如果是那么上面的分支情况都考虑到了,如果不是never类型那么上面的分支有遗漏
}
}
console.log(area({kind:"circle",r:1}))
字面量类型
可以把一个字面量的值作为一种类型叫做字面量类型
一般情况下,声明一个name变量会以以下方式进行赋值
let name :string = "Mr.Lee" //这表示name可以是任意string类型的值
如果我们想指定该变量为某一特定字符串的值,会以以下方式
let name:"Mr.Lee"= "Mr.Lee" // 这表示name的值只能是"Mr.Lee"
如果我们将name的值改为另一个字符串
let nam:"Mr.Lee"="Mr.M";
索引类型
索引类型的查询操作符
keyof T//表示类型T的所有公共属性的字面量的联合类型
interface Obj{
a:number
b:number
}
let key : keyof Obj//key的类型就是a|b的联合类型
索引访问操作符
T[value]//对象T的属性key所代表的类型
interface Obj{
a:number
b:number
}
let value:Obj[a]//表示Obj的属性a所代表的类型,a的类型为number因此value的类型为number
映射类型
interface Obj{
a:string
b:number
c:boolean
}
type ReadonlyObj = Readonly<Obj>
这样就把Obj中的属性变为只读类型
interface Obj{
a:string
b:number
c:boolean
}
type partialType = partial<Obj>
将Obj中的所有属性变成可选的。
实现原理
type Readonly<T>={
readonly [P in keyof T]:T[P];
}
Readonly是一个可索引的泛型接口,keyof T 索引类型的查询操作符,表示T的所有属性的联和类型,p in 相当于执行for……in循环操作,把变量P依次绑定到T的所有属性上,T[P]是索引类型的索引访问操作符,代表T的属性P代表的类型,然后通过readonly修饰符,将属性变为只读
条件类型
由条件表达式所决定的类型,增加了变量类型的灵活性和不唯一性
//T extends U?X:Y;如果类型T可以被复制给类型U结果类型就是X类型否则就是Y类型
type TypeName<T>=
T extends string ? "string" :
T extends number ? "number" :
T extends boolean ? "boolean" :
T extends undefined ? "undefined" :
T extends Function ? "function" :
"object";
type T1 = TypeName<string[]>//object类型
type T2 = TypeName<string>//string类型
type T3 = TypeName<string | string[]>//string类型和objec类型的联和类型
type Diff<T,U>=T extends U ? never : T
let T4 = Diff<"a" | "b" | "c","a" | "b">
//Diff<"a","a" | "b"> | Diff<"b","a" | "b"> | Diff<"c","a" | "b">
//"never" | "b" | "c"
//"b" | "c"