typescript的核心原則之一就是對所具備的shape類型檢查結構性子類型化 One of the core principles of typescript is to check structural subtyping of shape types 在typescript中,接口的做用就是爲這些類型命名和爲你的代碼或第三方代碼定義契約 In typescript, the function of an interface is to name these types and define contracts for your code or third-party code.git
function printLable(labelledObj:{label:string}){ console.log(labelledObj.label); } let myObj={size:10,label:"Size 10 Object"}; printLable(myObj);
咱們分析代碼能夠知道,一個對象有label對象,它的值類型是string類型 If we analyze the code, we can see that an object has a label object whose value type is string type. 使用接口重寫上面的例子 Rewrite the above example using an interfacetypescript
interface LabelledValue{ label:string; } function printLable(labelledObj:LabelledValue){ console.log(labelledObj.label); } let myObj={Size:10,label:"Size 10 Object"}; printLable(myObj); //類型檢查器不會去檢查屬性的順序,只要相應的屬性存在而且類型也是對的就能夠 /*The type checker does not check the order of attributes, as long as the corresponding attributes exist and the type is correct.*/
可選屬性。option bags 模式時很經常使用。接口裏的屬性不會都是必選的。有些只是在某些條件下存在,或者根本不存在 Optional properties. Option bags mode is often used. Attributes in interfaces are not always required. Some exist only under certain conditions, or nonexistent at all. 即給函數傳入的參數對象中只有部分屬性賦值了。 That is to say, only part of the parameter object passed in by the function is assigned to its attributes.數組
interface SquareConfig{ color?:string; width?:number; } function createSquare(config:SquareConfig):{color:string;area:number}{ let newSquare={color:"white",area:100}; if(config.color){ newSquare.color=config.color; } if(config.width){ newSquare.area=config.width*config.width; } return newSquare; } let mySquare=createSquare({color:"black"});
只讀屬性 Read-only attributeide
interface Point{ readonly x:number; readonly y:number; }
經過賦值一個對象字面量來構造一個Point Constructing a Point by assigning an object literal函數
let p1:Point={x:20,y:20}; p1.x=5;//error
typescript具備readonlyArray<T>類型,它與Array<T>類似,只是把全部可變方法去掉了 Typeescript has the readonlyArray < T > type, which is similar to Array < T > except that all the variable methods are removed. 所以能夠確保數組建立後不再能被修改 So you can make sure that arrays can never be modified after they are created.ui
let a:number[]=[1,2,3,4]; let ro:ReadonlyArray<number>=a; ro[0]=12;//error ro.push(5);//error ro.length=100;//error a=ro;//error
用類型斷言重寫 Rewrite with type assertionsthis
a=ro as number[];
readonly vs const 最先判斷該用readonly仍是const的方法是要看把它做爲變量使用仍是做爲一個屬性 The earliest way to determine whether to use readonly or const is to use it as a variable or as an attribute 做爲變量使用的話用const,若做爲屬性使用則用readonly Use const as a variable and read only as an attribute 額外的屬性檢查 Additional property checkingcode
interface SquareConfig{ color?:string; width?:number; } function createSquare(config:SquareConfig):{color:string;area:number}{ }
對象字面量會被特殊對待並且會通過 額外屬性檢查,當將它們賦值給變量或做爲參數傳遞的時候。 Object literals are treated specially and are checked for additional attributes when they are assigned to variables or passed as parameters. 若是一個對象字面量存在任何「目標類型」不包含的屬性時,你會獲得一個錯誤。 If an object literal has any attributes that the "target type" does not contain, you get an error.orm
let mySquare=createSquare({colour:"red",width:100});
繞開這些檢查很是簡單。 最簡便的方法是使用類型斷言: It's very simple to bypass these checks. The easiest way is to use type assertions:對象
let mySquare=createSquare({width:100,opacity:0.5}as SquareConfig);
最佳的方式是可以添加一個字符串索引簽名,前提是你可以肯定這個對象可能具備某些作爲特殊用途使用的額外屬性 The best way to do this is to be able to add a string indexed signature, provided you can determine that the object may have some additional properties for special purposes.
interface SquareConfig{ color?:string; width?:number; [proName:string]:any;//任意數量的屬性 }
它就是將這個對象賦值給一個另外一個變量: 由於squareOptions不會通過額外屬性檢查,因此編譯器不會報錯。 It assigns this object to another variable: because squareOptions does not undergo additional property checks, the compiler does not report errors.
let squareOptions = { colour: "red", width: 100 }; let mySquare = createSquare(squareOptions);
函數類型 Function Type 接口可以描述JavaScript中對象擁有的各類各樣的外形。 除了描述帶有屬性的普通對象外,接口也能夠描述函數類型。 Interfaces can describe the various shapes of objects in JavaScript. In addition to describing common objects with attributes, interfaces can also describe function types. 爲了使用接口表示函數類型,咱們須要給接口定義一個調用簽名。 它就像是一個只有參數列表和返回值類型的函數定義。參數列表裏的每一個參數都須要名字和類型。 In order to use interfaces to represent function types, we need to define a call signature for the interface. It's like a function definition with only parameter lists and return value types. Each parameter in the parameter list needs a name and type.
interface SearchFunc{ (source:string,subString:string):boolean; }
這樣定義後,咱們像使用其餘接口意義使用這個函數型的接口 如何建立一個函數類型的變量並將一個同類型函數賦值給這個變量 With this definition, we use this functional interface in the sense of other interfaces. How to create a variable of function type and assign a function of the same type to the variable
let mySearch:SearchFunc; mySearch=function(source:string,subString:string){ let result=source.search(subString); if(result==-1){ return false; }else{ return true; } }
對於函數類型的類型檢查來講,函數的參數名不須要與接口裏定義的名字相匹配 For type checking of function types, the parameter name of a function does not need to match the name defined in the interface.
let mySearch:SearchFunc; mySearch=function(src:string,sub:string):boolean{ let result=src.search(sub); if(result==-1){ return false; }else { return true; } } let mySearch:SearchFunc; mySearch=function(src,sub){ let result=src.search(sub); if(result==-1){ return false; }else{ return true; } }
可索引的類型 Indexable types
interface StringArray{ [index:number]:string; // 這個索引簽名表示了當用 number去索引StringArray時會獲得string類型的返回值。 //This index signature represents the return value of string type when StringArray is indexed with number. } let myArray:StringArray; myArray=["bob","tine"]; let myStr:string=myArray[0]; class Animal{ name:string; } class Dog extends Animal{ breed:string; } interface NotOkay{ [x:number]:Animal; [x:string]:Dog; }
字符串索引簽名可以很好的描述dictionary模式,而且它們也會確保全部屬性與其返回值類型相匹配。 由於字符串索引聲明瞭 obj.property和obj["property"]兩種形式均可以。 String indexed signatures describe dictionary patterns well, and they also ensure that all attributes match their return value types. Because the string index declares that both obj. property and obj ["property"] can be used.
interface NumberDictionary{ [index:string]:number; length:number; name:string; //name的類型不是索引類型的子類型 //The type of name is not a subtype of the index type }
將索引類型設置爲只讀,這樣就防止了給索引賦值 Setting the index type to read-only prevents index assignment
interface ReadonlyStringArray{ readonly [index:number]:string; } let myArray:ReadonlyStringArray=["Alice","Bob"]; myArray[2]="Mallory";//error
類類型 Class type TypeScript也可以用它來明確的強制一個類去符合某種契約。 TypeScript can also be used to explicitly force a class to conform to a contract.
interface ClockInterface{ currentTime:Date; } class Clock implements ClockInterface{ currentTime:Date; constructor(h:number,m:number){} }
在接口中描述一個方法,在類裏實現它,如同下面的setTime方法同樣: Describe a method in the interface and implement it in the class, just like the setTime method below:
interface ClockInterface{ currentTime:Date; setTime(d:Date); } class Clock implements ClockInterface{ currentTime:Date; setTime(d:Date){ this.currentTime=d; } constructor(h:number,m:number){} }
接口描述了類的公共部分,而不是公共和私有兩部分。 它不會幫你檢查類是否具備某些私有成員。 Interfaces describe the public part of a class, not the public and private parts. It doesn't help you check whether a class has some private members. 類靜態部分與實例部分的區別 The Difference between Class Static Part and Example Part ColockConstuctor爲構造函數所用 ColockConstuctor for constructors ClockInterface爲實例方法所用 ClockInterface for instance methods
interface ClockConstuctor{ new(hour:number,minute:number):ClockInterface; } interface ClockInterface{ tick(); } function createClock(ctor:ClockConstuctor,hour:number,minute:number): ClockInterface{ return new ctor(hour,minute); } class DigitalClock implements ClockInterface{ constructor(h:number,m:number){} tick(){ console.log("beep beep"); } } class AnalogClock implements ClockInterface{ constructor(h:number,m:number){} tick(){ console.log("tick tock") } } let digital=createClock(DigitalClock,12,17); let analog=createClock(AnalogClock,7,32);
擴展接口 Extended interface
interface Shape{ color:string; } interface Square extends Shape{ sideLength:number } let square=<Square>{}; square.color="blue"; square.sideLength=10;
一個接口能夠繼承多個接口,建立出多個接口的合成接口 An interface can inherit multiple interfaces and create a composite interface of multiple interfaces.
interface Shape { color: string; } interface PenStroke { penWidth: number; } interface Square extends Shape,PenStroke{ sideLength:number; } let square=<Square>{}; square.color="blue"; square.sideLength=10; square.penWidth=5.0;
混合類型 Mixed type 一個對象能夠同時做爲函數和對象使用,並帶有額外的屬性 An object can be used as both a function and an object with additional attributes
interface Counter{ (start:number):string; interval:number; reset():void; } function getCounter():Counter{ let counter=<Counter>function(start:number){}; counter.interval=123; counter.reset=function(){}; return counter; } let c=getCounter(); c(10); c.reset(); c.interval=5.0;
接口繼承類 Interface inheritance class
class Control { private state: any; } interface SelectableControl extends Control { select(): void; } class Button extends Control { select() { } } class TextBox extends Control { select() { } } class Image { select() { } } class Location { select() { } }