一、接口(interface):对行为和动作的规范,对批量方法进行约束
1.属性接口
/* 属性类型接口 */ interface FullName { firstName: string; /* 必传参数,接口分号间隔 */ secondName?: string; /* 问号表示可选参数,可传可不传 */ } function printName(name: FullName) { console.log(name.firstName, name.secondName) /* zhang undefined */ } let obj = { firstName: 'zhang', age: 18 } /* 参数声明再传入时,保证必传参数传入就不会报错,比如多传入age */ printName(obj)
2.函数接口
/* 函数类型接口 */ interface info { (value: string, id: number): string; } let getInfo: info = function (value: string, id: number): string { return value + id /* zhangsan1 */ } console.log(getInfo('zhangsan', 1)) /* zhangsan1 */
3.可索引接口
/* 可索引接口,数组、对象的约束 */ interface infoArr { [index: number]: string /* 对数组的约束 */ } let dataArr: infoArr = ["1", "2"] interface infoObj { [index: string]: string /* 对对象的约束 */ } let dataObj: infoObj = { age: "1", name: "zhangsan" }
4.类类型接口
/* 类类型接口,属性+函数 */ interface Something { name: string do(value: string): void } class things implements Something { /* implements,实现接口 */ name: string; constructor(name: string) { this.name = name } do() { /* 必须含有name和do() */ console.log(this.name + '玩游戏') /* zhangsan玩游戏 */ } } let s = new things('zhangsan') s.do()
二、接口继承接口
interface Animal { name: string do(value: string): void } interface Cat extends Animal { /* 接口继承接口 */ name: string eat(value: string): void } class things implements Cat { /* 实现Cat接口,也必须含有Animal接口的eat方法 */ name: string; constructor(name: string) { this.name = name } do() { console.log('Animal接口的方法') } eat() { console.log('Cat接口的方法') } }
三、泛型:用于解决类接口的复用性,以及解决不特定数据类型的支持
1.什么是泛型?
软件工程中,我们不仅要创建一致的定义良好的API,同时也要考虑可重用性。 组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,这在创建大型系统时为你提供了十分灵活的功能。
在像C#和Java这样的语言中,可以使用泛型
来创建可重用的组件,一个组件可以支持多种类型的数据。 这样用户就可以以自己的数据类型来使用组件。
举个例子,不用泛型的话,这个函数可能是下面这样:
function getData1(value:string):string{ return value } function getData2(value:number):number{ return value }
或者,我们使用any
类型来定义函数,但是这也等于放弃了类型检查:
function getData(value:any):any{ return value }
如果使用泛型的话,可以支持不特定的数据类型,要求就是传入和返回的类型一致,具体返回什么类型,由调用的时候决定
2.泛型的使用:
添加类型变量T
。 T
帮助我们捕获用户传入的类型(比如:number
),之后我们就可以使用这个类型。 之后我们再次使用了 T
当做返回值类型。现在我们可以知道参数类型与返回值类型是相同的了。 这允许我们跟踪函数里使用的类型的信息。
2.1泛型函数
function getData<T>(value:T):T{ return value }
2.2泛型类
class Getdata<T>{ list: T[] = []; add(value: T): void { this.list.push(value) } min(): T { var min = this.list[0]; this.list.forEach(function (value) { if (value < min) { min = value; } }); return min; } } let g=new Getdata<number>() g.add(4) g.add(2) g.add(1) g.add(3) console.log(g.min()) // 1
let gd=new Getdata<string>() gd.add('d') gd.add('b') gd.add('a') gd.add('c') console.log(gd.min()) // a
2.3泛型接口
interface Config{ <T>(value:T):T } let getData:Config=function<T>(value:T):T{ return value } console.log(getData('zhangsan')) // zhangsan
我们可能想把泛型参数当作整个接口的一个参数。 这样我们就能清楚的知道使用的具体是哪个泛型类型(比如:Config<string>而不只是Config
)。 这样接口里的其它成员也能知道这个参数的类型了。
interface Config<T>{ <T>(value:T):T } // 传入一个类型参数来指定泛型类型(这里是:string),锁定了之后代码里使用的类型。 let getData:Config<string>=function<T>(value:T):T{ return value } console.log(getData('zhangsan')) // zhangsan