联合类型和类型保护
联合类型 |
// 联合类型和类型保护 interface Bird { fly: boolean sing: () => {} } interface Dog { fly: boolean bark: () => {} } //联合类型 function trainAnial(animal: Bird | Dog) { // 使用联合类型的话ts不知道你的animal是哪个interface,所以会报错 animal.sing() } //类型保护 //这个时候就要用到类型断言,比如下面的(类型断言as的方式进行类型保护) function trainAnial(animal: Bird | Dog) { if (animal.fly) { ;(animal as Bird).sing() } ;(animal as Dog).bark() } // 类型保护第二种方法(in 语法来做类型保护) function trainAnialSecond(animal: Bird | Dog) { if ('sing' in animal) { animal.sing() } else { animal.bark() } } // 类型保护第三种方法(typeof语法做类型保护) function add(first: string | number, second: string | number) { if (typeof first === 'string' || typeof second === 'string') { return `${first}${second}` } return first + second } // 类型保护第四种方法(instanceof语法做类型保护)(只能用于class,不能用class) class NumberObj { count: number = 0 } function addSecond(first: object | NumberObj, second: object | NumberObj) { if (first instanceof NumberObj && second instanceof NumberObj) { return first.count + second.count } return 0 }
枚举类型(可正查反查)
//枚举(可正查反查) enum Status { OFFline, online, deleted, } console.log(Status) console.log(Status[0]) //OFFline console.log(Status.OFFline) //0 // { // '0': 'OFFline', // '1': 'online', // '2': 'deleted', // OFFline: 0, // online: 1, // deleted: 2 // } enum Status1 { OFFline = 1, online, deleted, } console.log(Status1) // { // '1': 'OFFline', // '2': 'online', // '3': 'deleted', // OFFline: 1, // online: 2, // deleted: 3 // }
泛型 generic 泛指的类型
// 泛型 generic 泛指的类型 function join<T, P>(first: T, second: P): T { return first } join<string, string>('1', '2') function map<ABC>(params: Array<ABC>) { return params } map<string>(['123'])
类中的泛型以及泛型类型
//类中的泛型
interface Item {
name: string
}
// T继承了Item,表示T里面一定要有Item的所有属性
class DataManager<T extends Item> {
constructor(private data: T[]) {}
getItem(index: number): string {
return this.data[index].name
}
}
const data = new DataManager([{ name: '11' }])
// 泛型约束(用extends 联合类型或interface)
class DataManager2<T extends number | string> {
constructor(private data: T[]) {}
getItem(index: number): T {
return this.data[index]
}
}
interface Test {
name: string
}
const data = new DataManager2<number>([])
console.log(data.getItem(0))
// 如何使用泛型作为一个具体的类型注解
function hello<T>(param: T) {
return param
}
const func: <T>(param: T) => T = hello
namespace 命名空间(类似与模块化,闭包,外部访问不到里面的变量,只有export部分变量才可以被外部访问到)
//namespace 形成闭包,只把Home暴露出去,其他三个方法访问不了 namespace Home { class Header { constructor() { const elem = document.createElement('div'); elem.innerText = 'This is Header'; document.body.appendChild(elem); } } class Content { constructor() { const elem = document.createElement('div'); elem.innerText = 'This is Content'; document.body.appendChild(elem); } } class Footer { constructor() { const elem = document.createElement('div'); elem.innerText = 'This is Footer'; document.body.appendChild(elem); } } //namespace export(只导出Page,可以通过 new Home.Page访问得到) export class Page { constructor() { new Header(); new Content(); new Footer(); } } }
全局类型(自己定义一个.d.ts文件)
也可以写成下面这种interface的语法,实现函数重载
上面是对变量和函数进行类型定义,下面是对对象进行类型定义
模块代码的类型描述文件(es6模块化d.ts,最后记得export导出)
泛型中keyof语法的使用
interface Person {
name: string
age: number
gender: string
}
//帮助理解
// type NAME = 'name';
// key: 'name';
// Person['name'];
// type T = 'age'
// key: 'age'
// Person['age']
// type T = 'gender'
// key: 'gender'
// Person['gender']
// 用泛型结合keyof的方式解决key值不准确的问题
// 1、keyof是遍历循环Person的key
// 2、例如 T extends name => 恒等于 type T = name 所以 参数key:name
class Teacher {
constructor(private info: Person) {}
getInfo<T extends keyof Person>(key: T): Person[T] {
return this.info[key]
}
}
const teacher = new Teacher({
name: 'zhen',
age: 28,
gender: 'male',
})
const test = teacher.getInfo('age')
console.log(test)