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')