1.接口
interface 描述对象的形状和结构,可以给数据增添类型 而且方便复用
- interface 可以被类实现 和继承 , type没有功能
- type 可以使用联合类型 interface 不能使用联合类型
1.如何用接口描述对象类型 , 如果有联合类型 就使用type
let school = { // 接口默认的功能是规范类型的
name: 'zf',
age: 12
}
// 类型反推 就是根据代码推导出一个类型,方便使用
type schools = Array<typeof school>;
function aa(school: schools) {
}
aa([{ name: 'zf', age: 123 }]);
2.描述函数类型
interface ISum {
(a: string, b: string): string
}
// type ISum = (a:string,b:string)=>string
const sum: ISum = (a, b) => {
return a + b;
}
3. 接口的特性
interface IVegetables {
color:string,
taste:string
}
1 直接断言,断言后可以直接使用 (要保证接口中限制的数据必须要有)
const tomato:IVegetables = {
color:'red',
taste:'sweet',
size:'big'
} as IVegetables
2.接口的合并 接口同名会合并,会改变原有的接口
interface IVegetables {
size:string
}
const tomato:IVegetables = {
color:'red',
taste:'sweet',
size:'big'
}
3) 接口的继承
interface ITomato extends IVegetables{ // 接口的继承 ts里面的
size:string
}
const tomato:ITomato = {
color:'red',
taste:'sweet',
size:'big'
}
4) 可选属性 可以通过? 来实现
interface IVegetables {
color: string,
taste: string,
[key: string]: any // 任意接口 可多填
// size?:string // 函数的参数
// id?:number
}
5) 接口实现 接口可以被类来实现 , 接口中的方法都是抽象(没有具体实现)的
interface ISpeakable {
name: string,
// 用接口来形容类的时候 void 表示不关心返回值
speak(): void // 描述当前实例上的方法,或者原型的方法
}
interface IChineseSpeakable {
speakChinese(): void
}
class Speak implements ISpeakable, IChineseSpeakable { // 剋本身需要实现接口中的方法
speakChinese(): void {
throw new Error("Method not implemented.");
}
name!: string
speak(): string { // 此方法是原型方法
return 'xxx'
}
}
let s = new Speak()
6.抽象类 不能被new, 可以被继承
abstract class Animal { // 只有类被标记成abstract 属性在可以描述成abstract的
abstract name: string// 没有具体实现,需要子类实现
eat() {
console.log('eat')
}
abstract drink(): void
}
class Cat extends Animal {
drink(): void {
console.log('Method not implemented')
}
name: string = 'a'
}
泛型
泛型的用处在于 当我们调用的时候 确定类型,而不是一开始就写好类型,类型不确定,只有在执行的时候才能确定
1.单个泛型 声明的时候 需要用 <>包裹起来, 传值的时候也需要
function createArray<T>(times: number, value: T): Array<T> { // 根据对应参数的类型给T赋值
let result = [];
for (let i = 0; i < times; i++) {
result.push(value)
}
return result
}
let r = createArray(5, 'abc');
2.多个泛型 元组进行类型交换
const swap = <T, K>(tuple: [T, K]): [K, T] => { // 元组是特殊的数组
return [tuple[1], tuple[0]]
}
let r = swap([{}, 'xx']); // => [123,'abc'] 我能确定只有两项
const sum = <T extends string>(a: T, b: T): T => { // 约束对象
return (a + b) as T
}
sum('a','v')
3) 泛型约束 主要强调类型中必须包含某个属性
type withLen = { length: number }
const computeArrayLength = <T extends withLen, K extends withLen>(arr1: T, arr2: K): number => {
return arr1.length + arr2.length
}
computeArrayLength('123', { length: 3 })
const getVal = <T extends object, K extends keyof T>(obj: T, key: K) => {
if (typeof obj !== 'object') {
return
}
}
type T1 = keyof { a: 1, b: 2 }
type T2 = keyof string
type T3 = keyof any; // string |number | symbol
getVal({ a: 1, b: 2 }, 'a')
3.泛型可以给类来使用
class GetArrayMax<T = number> { // [1,2,3] [a,b,c]
public arr: T[] = [];
add(val: T) {
this.arr.push(val)
}
getMax():T {
let arr = this.arr;
let max = arr[0];
for (let i = 1; i < arr.length; i++) {
arr[i] > max ? max = arr[i] : null
}
return max;
}
}
let arr = new GetArrayMax(); // 泛型只有当使用后才知道具体的类型
arr.add(1);
arr.add(2)
arr.add(3)
let r = arr.getMax()
4.泛型可以在 函数 类 (接口、别名) 中使用
// extends 约束 keyof 取当前类型的key typeof 取当前值的类型
interface ISchool <T = number>{
name:T
}
type BoolSchool = ISchool<boolean>
type NumberSchool = ISchool