泛型1
泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性
首先,我们来实现一个函数 createArray
function createArray(length: number, value: any): Array<any> { let result = []; for (let i = 0; i < length; i++) { result[i] = value; } return result; } createArray(3, 'x'); // ['x', 'x', 'x']
这段代码编译不会报错,但是一个显而易见的缺陷是,它并没有准确的定义返回值的类型
Array 允许数组的每一项都为任意类型。但是我们预期的是,数组中每一项都应该是输入的 value 的类型
这时候,泛型就派上用场了
function createArray<T>(length: number, value: T): Array<T> { let result: T[] = []; for (let i = 0; i < length; i++) { result[i] = value; } return result; } createArray<string>(3, 'x'); // ['x', 'x','x']
泛型2
多个类型参数
function swap<T, U>(v1:T,v2:U) { console.log(v1,v2) } swap(10,20);
泛型约束
在函数内部使用泛型变量的时候,由于事先不知道它是哪种类型,所以不能随意的操作它的属性或方法
function loggingLength<T>(arg: T){ // Property 'length' does not exist on type 'T' console.log(arg.length); }
这时,我们可以对泛型进行约束,只允许这个函数传入那些包含 length 属性的变量。这就是泛型约束
interface Length { length: number; } function loggingIdentity<T extends Length> (arg: T){ console.log(arg.length); } loggingIdentity("Hello")
声明合并
如果定义了两个相同名字的函数、接口或类,那么它们会合并成一个类型
函数的合并
我们可以使用重载定义多个函数类型
function reverse(x: number): number; function reverse(x: string): string; function reverse(x: number | string): number | string { if (typeof x === 'number') { return Number(x.toString().split('').reverse().join('')); } else if (typeof x === 'string') { return x.split('').reverse().join(''); } }
接口的合并
接口中的属性在合并时会简单的合并到一个接口中
interface Alarm { price: number; } interface Alarm { weight: number; }
相当于:
interface Alarm { price: number; weight: number; }
注意,合并的属性的类型必须是唯一的:
interface Alarm { price: number; } interface Alarm { price: number; // 虽然重复了,但是类型都是 `number`,所以不会报错 weight: number; }
interface Alarm { price: number; } interface Alarm { price: string; // 类型不一致,会报错 weight: number; }
命名空间
在真实的应用场景中,当在一个文件中代码量过多,不容易阅读和维护的时候,我们可以通过命名空间的方式将一个文件分离为多个文件
我们来观察下面这个例子:
interface Animal{ name:string } class Cat implements Animal{ name: string constructor(name:string){ this.name = name; } sayHi(){ console.log(this.name) } } class Dog implements Animal{ name: string constructor(name:string){ this.name = name } sayHello(){ console.log(this.name) } } const c = new Cat("猫") c.sayHi() const d = new Dog("狗") d.sayHello()
当应用变得越来越大时,我们需要将代码分离到不同的文件中以便于维护
// Animal.ts namespace AnimalInfo{ export interface Animal{ name:string } }
// Cat.ts namespace AnimalInfo{ export class Cat implements Animal{ name: string constructor(name:string){ this.name = name; } sayHi(){ console.log(this.name) } } }
// Dog.ts namespace AnimalInfo{ export class Dog implements Animal{ name: string constructor(name:string){ this.name = name } sayHello(){ console.log(this.name) } } }
// index.ts const c = new AnimalInfo.Cat("猫") c.sayHi() const d = new AnimalInfo.Dog("狗") d.sayHello()
TypeScript【泛型1、泛型2、声明合并、命名空间 、模块1、模块2、声明文件简介】(五)-全面详解(学习总结---从入门到深化)(下):https://developer.aliyun.com/article/1420374