TypeScript 中介面詳解

來源:互聯網
上載者:User

TypeScript 中介面詳解

   TypeScript核心設計原則之一就是類型檢查,通過使用介面(Interfaces)可以進行類型檢查,滿足傳統物件導向思想,利於有效開發,有效避免類型轉換問題。

  在 TypeScript 中,介面是用作約束作用的,在編譯成 JavaScript 的時候,所有的介面都會被擦除掉,因為 JavaScript 中並沒有介面這一概念。

  先看看一個簡單的例子:

  ?

1

2

3

4

5

6

function printLabel(labelledObj: { label: string }) {

console.log(labelledObj.label);

}

 

var myObj = { size: 10, label: "Size 10 Object" };

printLabel(myObj);

  那麼在該方法中,labelledObj 的類型就是 {label: string},看上去可能有點複雜,但我們看見看看下面 myObj 的聲明就知道,這是聲明了一個擁有 size 屬性(值為 10)和 label 屬性(值為 "Size 10 Object")的對象。所以方法參數 labelledObj 的類型是 {label: string} 即表明參數擁有一個 string 類型的 label 屬性。

  但是,這麼寫的話,這個方法看上去還是有點讓人糊塗。那麼就可以用介面(interface)來定義這個方法的參數類型。

  ?

1

2

3

4

5

6

7

8

9

10

interface LabelledValue {

label: string;

}

 

function printLabel(labelledObj: LabelledValue) {

console.log(labelledObj.label);

}

 

var myObj = { size: 10, label: "Size 10 Object" };

printLabel(myObj);

  可選屬性

  有些時候,我們並不需要屬性一定存在,就可以使用可選屬性這一特性來定義。

  ?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

interface SquareConfig {

color?: string;

width?: number;

}

 

function createSquare(config: SquareConfig): { color: string; area: number } {

var newSquare = { color: "white", area: 100 };

if (config.color) {

newSquare.color = config.color;

}

if (config.width) {

newSquare.area = config.width * config.width;

}

return newSquare;

}

 

var mySquare = createSquare({ color: "black" });

  那麼我們就傳入了實現一個 SquareConfig 介面的對象入 createSquare 方法。

  既然完全是可有可無的,那麼為什麼還要定義呢?對比起完全不定義,定義可選屬性有兩個優點。1、如果存在屬性,能約束類型,這是十分關鍵的;2、能得到文法智能提示,假如誤將方法體中 color 寫成 collor,那麼編譯是不通過的。

  方法類型

  在 JavaScript 中,方法 function 是一種基本類型。在物件導向思想中,介面的實現是靠類來完成的,而 function 作為一種類型,是不是能夠實現介面呢?答案是肯定的。

  在 TypeScript 中,我們可以使用介面來約束方法的簽名。

  ?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

interface SearchFunc {

(source: string, subString: string): boolean;

}

 

var mySearch: SearchFunc;

mySearch = function(source: string, subString: string) {

var result = source.search(subString);

if (result == -1) {

return false;

}

else {

return true;

}

}

  上面代碼中,我們定義了一個介面,介面內約束了一個方法的簽名,這個方法有兩個字串參數,返回布爾值。在第二段代碼中我們聲明了這個介面的實現。

  需要注意的是,編譯器僅僅檢查類型是否正確(參數類型、傳回值類型),因此參數的名字我們可以換成別的。

  ?

1

2

3

4

5

6

7

8

9

10

var mySearch: SearchFunc;

mySearch = function(src: string, sub: string) {

var result = src.search(sub);

if (result == -1) {

return false;

}

else {

return true;

}

}

  這樣也是能夠編譯通過的。

  數群組類型

  在上面我們在介面中定義了方法類型,那麼,數群組類型又應該如何定義呢?很簡單。

  ?

1

2

3

4

5

6

interface StringArray {

[index: number]: string;

}

 

var myArray: StringArray;

myArray = ["Bob", "Fred"];

  那麼 myArray 就是一個數組,並且索引器是 number 類型,元素是 string。

  在介面的定義裡面,索引器的名字一般為 index(當然也可以改成別的,但一般情況下都是保持名字為 index)。所以改成

  ?

1

2

3

4

5

6

interface StringArray {

[myIndex: number]: string;

}

 

var myArray: StringArray;

myArray = ["Bob", "Fred"];

  也是 ok 的。

  需要注意的是,索引器的類型只能為 number 或者 string。

  ?

1

2

3

4

5

6

7

interface Array{

[index: number]: any;

}

 

interface Dictionary{

[index: string]: any;

}

  上面兩段都是可以編譯通過的。

  最後還有一點要注意的是,如果介面已經是數群組類型的話,介面中定義的其它屬性的類型都必須是該數組的元素類型。例如:

  ?

1

2

3

4

interface Dictionary {

[index: string]: string;

length: number; // error, the type of 'length' is not a subtype of the indexer

}

  那麼將無法編譯通過,需要將 length 改成 string 類型才可以。

  使用類實現介面

  一般情況下,我們還是習慣使用一個類,實現需要的介面,而不是像上面直接用介面。

  ?

1

2

3

4

5

6

7

8

interface ClockInterface {

currentTime: Date;

}

 

class Clock implements ClockInterface {

currentTime: Date;

constructor(h: number, m: number) { }

}

  在 TypeScript 中,使用 class 關鍵字來聲明了,這跟 EcmaScript 6 是一樣的。

  另外,我們可以使用介面來約束類中定義的方法。

  ?

1

2

3

4

5

6

7

8

9

10

11

12

interface ClockInterface {

currentTime: Date;

setTime(d: Date);

}

 

class Clock implements ClockInterface {

currentTime: Date;

setTime(d: Date) {

this.currentTime = d;

}

constructor(h: number, m: number) { }

}

  在 TypeScript 中,我們可以為介面定義建構函式。

  ?

1

2

3

interface ClockInterface {

new (hour: number, minute: number);

}

  接下來天真的我們可能會接著這麼寫:

  ?

1

2

3

4

5

6

7

8

interface ClockInterface {

new (hour: number, minute: number);

}

 

class Clock implements ClockInterface {

currentTime: Date;

constructor(h: number, m: number) { }

}

  這是不行的!!!因為建構函式是 static(靜態)的,而類僅能夠實現介面中的 instance(執行個體)部分。

  那麼這個介面中定義的建構函式豈不是沒作用?既然 TypeScript 提供了這項功能,那麼肯定不會是沒作用的。聲明的方法比較特殊:

  ?

1

2

3

4

5

6

7

8

9

10

11

interface ClockStatic {

new (hour: number, minute: number);

}

 

class Clock {

currentTime: Date;

constructor(h: number, m: number) { }

}

 

var cs: ClockStatic = Clock;

var newClock = new cs(7, 30);

  正常情況下我們是寫 new Clock 的,這裡就將 Clock 類指向了 ClockStatic 介面。需要注意的是,newClock 變數的類型是 any。

  繼承介面

  像類一樣,介面也能實現繼承,使用的是 extends 關鍵字。

  ?

1

2

3

4

5

6

7

8

9

10

11

interface Shape {

color: string;

}

 

interface Square extends Shape {

sideLength: number;

}

 

var square = <Square>{};

square.color = "blue";

square.sideLength = 10;

  當然也能繼承多個介面。

  ?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

interface Shape {

color: string;

}

 

interface PenStroke {

penWidth: number;

}

 

interface Square extends Shape, PenStroke {

sideLength: number;

}

 

var square = <Square>{};

square.color = "blue";

square.sideLength = 10;

square.penWidth = 5.0;

  需要注意的是,儘管支援繼承多個介面,但是如果繼承的介面中,定義的同名屬性的類型不同的話,是不能編譯通過的。

  ?

1

2

3

4

5

6

7

8

9

10

11

12

13

interface Shape {

color: string;

test: number;

}

 

interface PenStroke {

penWidth: number;

test: string;

}

 

interface Square extends Shape, PenStroke {

sideLength: number;

}

  那麼這段代碼就無法編譯通過了,因為 test 屬性的類型無法確定。

  同時使用上面所述的類型

  如果僅能單一使用某種類型,那麼這介面也未免太弱了。但幸運的是,我們的介面很強大。

  ?

1

2

3

4

5

6

7

8

9

10

interface Counter {

(start: number): string;

interval: number;

reset(): void;

}

 

var c: Counter;

c(10);

c.reset();

c.interval = 5.0;

  這樣就使用到三種類型了,分別是方法(介面自己是個方法)、屬性、方法(定義了方法成員)。

  以上所述就是本文的全部內容了,希望大家能夠喜歡。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.