1.高级类型都有哪些
- 交叉类型
- 联合类型
- 类型保护
- 可为null的类型
- 字符串字面量类型
2.交叉类型
function extend(<T, U>(first: T, second: U)): T&U {
let result = {} as T&U
for (let id in first) {
result[id] = first[id] as any // 注意这里要断言成any
}
for (let id in second) {
if (!result.hasOwnProperty(id)) {
result[id] = second[id] as any
}
}
return result
}
class Person {
constructor(public name: string) {
}
}
interface Loggable {
log(): void
}
class ConsoleLogger implements Loggable {
log() {
...
}
}
var jim = extend(new Person('jim'), new ConsoleLogger()) // 返回的是一个交叉类型
jim.name // right
jim.log() // right
思考:那么如果Person中有private属性or方法,返回的交叉对象是否能访问到private?
3.联合类型
interface Bird {
fly()
layEggs()
}
interface Fish {
swim()
layEggs()
}
function getSmallPet(): Fish | Bird {
return Math.random() > 0.5 ? new Fish() : new Bird()
}
let pet = getSmallPet()
pet.layEggs() // right
pet.swim() // error
联合类型与交叉类型的区别是,交叉类型返回的是多个对象的和,而联合类型返回的是不确定的,因此在使用的时候要小心使用非公有的属性方法
解决办法: 使用类型保护
4.类型保护
interface Bird {
fly()
layEggs()
}
interface Fish {
swim()
layEggs()
}
function getSmallPet(): Fish | Bird {
return Math.random() > 0.5 ? new Fish() : new Bird()
}
let pet = getSmallPet()
// 初级
if ((pet as Fish).swim {
(pet as Fish).swim()
} else if ((pet as Bird).fly){
(pet as Bird).fly()
}
// 继续改造
function isFish(pet: Fish | Bird): pet is Fish {
return (pet as Fish).swim !== 'undefined'
}
if (isFish(pet)) {
pet.swim()
} else {
pet.fly()
}
5.可以为null的类型
command: tsc index.ts --strictNullChecks
// 对null进行断言保护
function broken(name: string | null): string {
function postfix(epitht: string) {
// 此处对name加上! 进行断言保护,明确不为null
return name!.charAt(0) + '.the' + epitht
}
name = name || 'Bob'
return postfix(name)
}
broken(null)
6.字符串字面量类型
type Easing = 'ease-in' | 'ease-out' | 'ease-in-out'
class UIElement {
animate(dx: number, dy: number, easing: Easing) {
if (easing === 'ease-in') {
// ...
} else if (easing === 'ease-out'){
// ...
} else if (easing === 'ease-in-out') {
// ...
} else {
// ...
}
}
}
let button = new UIElement()
button.animate(0, 0, 'ease-in')