接口 Interfaces
接口是一系列抽象方法的聲明,是一些方法特徵的集合,這些方法都應該是抽象的,需要由具體的類去實現,然後第三方就可以通過這組抽象方法調用,讓具體的類執行具體的方法。
接口(Interfaces)是一個很重要的概念,可以理解爲一種規範或者約束,用來描述 對象(object) 的形狀 或者對 類(class) 的行爲 進行抽象。對類的行爲抽象將在後面 類與接口 一章中介紹,下面主要介紹對對象的形狀進行描述。
接口定義
使用 interface 定義接口, 接口名稱一般首字母大寫,定義接口的時候,只定義聲明即可,不包含具體內容:
實現接口的時候,要實現裏面的內容,定義的變量比接口少了或多了屬性都是不允許的 。
// 接口是一系列抽象方法的聲明,是一些方法特徵的集合,這些方法都應該是抽象的,需要由具體的類去實現,然後第三方就可以通過這組抽象的方法調用,讓具體的類執行具體的方法。
// 關鍵字 interface
interface IPerson {
firstName: string,
lastName: string,
sayHi: () => string
}
// 具體實現Iperson類的對象
// 實現接口的時候,要實現裏面的內容,定義的變量比接口少了或多了屬性都是不允許的:
var stu: IPerson = {
firstName: 'muzidigbig',
lastName: 'Lee',
sayHi: (): string => {
return 'Hello! ' + stu.lastName + '.' + stu.firstName;
}
}
console.log(stu.firstName);
console.log(stu.sayHi());
需要注意接口不能轉換爲 JavaScript。 它只是 TypeScript 的一部分。
編譯以上代碼,得到以下 JavaScript 代碼:
// 具體實現Iperson類的對象
// 實現接口的時候,要實現裏面的內容,定義的變量比接口少了或多了屬性都是不允許的:
var stu = {
firstName: 'muzidigbig',
lastName: 'Lee',
sayHi: function () {
return 'Hello! ' + stu.lastName + '.' + stu.firstName;;
}
};
console.log(stu.firstName);
console.log(stu.sayHi());
可選屬性
使用 ? 代表可選屬性, 即該屬性可以不存在, 但不允許添加未定義的屬性
interface Person {
name: string;
age?: number;
}
let tom: Person = {
name: 'tom'
}
// age是可選屬性
任意屬性
定義了任意屬性後可以添加未定義的屬性,並可以指定屬性值的類型
interface Person2 {
firstName: string,
lastName: string,
age? : number,//可選屬性
[propName: string]: any,//任意屬性
sayHi: () => string
}
var stu2: Person2 = {
firstName: 'muzidigbig',
lastName: 'Lee',
age: 22,
sex: '男',
sayHi: (): string => {
return `我叫${stu2.firstName}.${stu2.lastName}-${stu2.sex}今年${stu2.age}`
}
}
stu2.age = 23;
console.log(stu2.age); //23
console.log(stu2.sayHi()); //我叫muzidigbig.Lee-男今年23
注意:定義了任意屬性,那麼確定屬性和可選屬性都必須是它的子屬性
interface Person2 {
firstName: string,
lastName: string,
age? : number,//可選屬性
[propName: string]: string,//任意屬性
}
// 編譯報錯:Person2定義了一個任意屬性,其值爲string類型。則Person的所有屬性都必須爲string類型,而age爲number類型
只讀屬性 readonly
interface Person3 {
readonly id: number,
name: string,
age?: number,
[propName: string]: any
}
只讀的約束存在於第一次給對象賦值的時候,而不是第一次給只讀屬性賦值的時候
var stu3:Person3 = {
id: 0,
name: 'muzidigbig',
age: 22
}
console.log(stu3.id);
// => 編譯報錯:id爲只讀, 不可修改
// stu3.id = 1;
函數類型接口
// 只有參數列表和返回值類型的函數定義, 參數列表裏的每個參數都需要名字和類型
interface SearchFunc {
(flg1: number, flg2: number): boolean;
}
// 用接口定義函數的形狀
interface FunFlg {
(flg1: number, flg2: number): boolean;
}
// 函數的參數名不需要與接口裏定義的名字相匹配
var flg: FunFlg;
flg = (value1: number,value2: number) => {
return value1 > value2;
}
console.log(flg(2,23)); //false
var flg2: FunFlg;
flg2 = (value1: number,value2: number) => {
return value1 < value2;
}
console.log(flg2(2,23)); //true
聯合類型和接口
//聯合類型和接口
interface RunOptions {
program: string,
commandlines: string[] | string | (() => string);
}
// commandline 是字符串
var options1: RunOptions = {
program: 'test1',
commandlines: 'this is name muzidigbig'
}
console.log(options1.commandlines);
// commandline 是字符串數組
var options2: RunOptions = {
program: 'test2',
commandlines: ['muzi','digbig']
}
// commandline 是一個函數表達式
var options3: RunOptions = {
program: 'test3',
commandlines: (): string => {
return options3.program;
}
}
var fn: any = options3.commandlines;
console.log(fn());
接口和數組
接口中我們可以將數組的索引值和元素設置爲不同類型,索引值可以是數字或字符串。常用作定義任意屬性
interface namelist {
[index:number]:string
}
var list2:namelist = ["John",1,"Bran"] / 錯誤元素 1 不是 string 類型
interface ages {
[index:string]:number
}
var agelist:ages;
agelist["John"] = 15 // 正確
agelist[2] = "nine" // 錯誤