TypeScript
接口git
使用關鍵字readonly定義只讀的接口屬性es6
interface Point { readonly x: number; readonly y: number; }
// 定義一個接口 interface Point{ readonly x: number; readonly y: number; } // 對接口賦值 let p1: Point = { x: 10, y: 20 }; p1.x = 5; // 該句錯誤,不能進行賦值操做
出現錯誤,以下
json
// 定義一個接口 interface Point{ readonly x: number; readonly y: number; } // 對接口賦值 let p1: Point = { x: 10, y: 20 }; //p1.x = 5; // 該句錯誤,不能進行賦值操做 let a: number[] = [1, 2, 3, 4, 5]; let ro: ReadonlyArray<number> = a; // 設置爲只讀的數組 ro[0] = 12; // 不可進行賦值。出現賦值錯誤
若是想要從新賦值,斷言重寫數組
當一個值有多個類型的時候,使用斷言重寫,肯定一個新的類型閉包
// 定義一個接口 interface Point{ readonly x: number; readonly y: number; } // 對接口賦值 let p1: Point = { x: 10, y: 20 }; //p1.x = 5; // 該句錯誤,不能進行賦值操做 let a = [2, 3, 4, 5]; let ro: ReadonlyArray<number> = [2, 3, 4, 5]; //ro[0] = 12; // 不可進行賦值 // 若是須要賦值,使用斷言重寫 a = ro as number[]; // 進行斷言重寫
// 對接口賦值 var p1 = { x: 10, y: 20 }; //p1.x = 5; // 該句錯誤,不能進行賦值操做 var a = [2, 3, 4, 5]; var ro = [2, 3, 4, 5]; //ro[0] = 12; // 不可進行賦值 // 若是須要賦值,使用斷言重寫 a = ro; // 進行斷言重寫 //# sourceMappingURL=out.js.map
類型斷言很大程度上能夠規範類型app
// 定義一個函數類型的接口 interface SearchFunc { (source: string, subString: string): boolean; // 定義一個函數類型的接口 } // 使用這個接口 let mySearch: SearchFunc; mySearch = (source:string,subString:string) => { let result = source.search(subString); // 兩個字符串正則匹配 return result > -1; }
// 使用這個接口 var mySearch; mySearch = function (source, subString) { var result = source.search(subString); // 兩個字符串正則匹配 return result > -1; }; //# sourceMappingURL=out.js.map
編譯器會逐個檢查,若是通通正確,則編譯經過,不然編譯不經過ide
// 定義索引接口 interface StringArray { [index: number]: string; } let myArray: StringArray; // 定義一個myArray的變量,類型爲索引接口 myArray = ["Bob", "Fred"]; let myStr: string = myArray[0]; // 取第一個值
var myArray; // 定義一個myArray的變量,類型爲索引接口 myArray = ["Bob", "Fred"]; var myStr = myArray[0]; // 取第一個值 //# sourceMappingURL=out.js.map
索引值內部必須所有爲number類型的
函數
// 定義接口,一個索引值類型的,其返回值也爲索引類型的 interface NumberDictionary{ [index: string]: number; length: number; // 能夠設置length name: string; // 錯誤索引值內部不能擁有string類型 }
編譯一下出現錯誤ui
索引簽名依舊能夠設置爲只讀,此時能夠防止給索引賦值。使用關鍵字readonlythis
// 定義接口 interface NumberDictionary { readonly [index: number]: string; } // 初始化一個變量 let myArray: NumberDictionary = ["hello", "world"];
順帶配置一下配置文件
// tsconfig.json { "compilerOptions": { "out": "built/out.js", "sourceMap": true, "target": "es5" }, "files": [ "greeter.ts" ] }
// out.js // 初始化一個變量 var myArray = ["hello", "world"]; //# sourceMappingURL=out.js.map
// 定義接口 interface NumberDictionary { readonly [index: number]: string; } // 初始化一個變量 let myArray: NumberDictionary = ["hello", "world"]; // 此時進行賦值爲錯誤的 myArray[2] = "hello world";
明確一個類去符合一種接口
// 定義接口 interface ClockInterFace { currentTime: Date; } class Clock implements ClockInterFace { // 使用implements 關鍵字clock類符合接口clockInterFace currentTime: Date; constructor(h:number, m:number){ // 定義構造函數 } }
// 注意在上方中並不會對靜態的,進行檢查。只會對非靜態的部分,即非構造函數部分進行檢查
var Clock = /** @class */ (function () { function Clock(h, m) { // 定義構造函數 } return Clock; }()); //# sourceMappingURL=out.js.map
若是配置成爲es6即
{ "compilerOptions": { "out": "built/out.js", "sourceMap": true, "target": "es6" }, "files": [ "greeter.ts" ] }
class Clock { constructor(h, m) { // 定義構造函數 } } //# sourceMappingURL=out.js.map
interface ClockInterface { currentTime: Date; setTime(d: Date); // 定義接口的方法 } class Clock implements ClockInterface{ currentTime: Date; // 接口檢查的 setTime(d:Date){ // 接口檢查的方法 this.currentTime = d; } constructor(h:number, m:number){ // 接口不會檢查靜態的構造方法 } }
var Clock = /** @class */ (function () { function Clock(h, m) { } Clock.prototype.setTime = function (d) { this.currentTime = d; }; return Clock; }()); //# sourceMappingURL=out.js.map
構造函數屬於靜態的方法,當構造器定義了一個靜態的方法的時候。構造器只檢查動態的方法,並不會檢查動態的方法,故,下方的寫法編譯器不經過
interface ClockConstructor { new (hour: number, minuter: number); // 定義構造函數的接口 }; class clock implements ClockConstructor { currenTime: Date; constructor(h:number, m:number){ // 接口限制的是此構造函數 } }interface ClockConstructor { new (hour: number, minuter: number); // 定義構造函數的接口 }; class clock implements ClockConstructor { currenTime: Date; constructor(h:number, m:number){ // 接口限制的是此構造函數 } }interface ClockConstructor { new (hour: number, minuter: number); // 定義構造函數的接口 }; class clock implements ClockConstructor { currenTime: Date; constructor(h:number, m:number){ // 接口限制的是此構造函數 } }interface ClockConstructor { new (hour: number, minuter: number); // 定義構造函數的接口 }; class clock implements ClockConstructor { currenTime: Date; constructor(h:number, m:number){ // 接口限制的是此構造函數 } }interface ClockConstructor { new (hour: number, minuter: number); // 定義構造函數的接口 }; class clock implements ClockConstructor { currenTime: Date; constructor(h:number, m:number){ // 接口限制的是此構造函數 } }interface ClockConstructor { new (hour: number, minuter: number); // 定義構造函數的接口 }; class clock implements ClockConstructor { currenTime: Date; constructor(h:number, m:number){ // 接口限制的是此構造函數 } }
編譯
PS C:\Users\mingm\Desktop\ts> tsc Active code page: 65001 greeter.ts:5:7 - error TS2420: Class 'clock' incorrectly implements interface 'ClockConstructor'. Type 'clock' provides no match for the signature 'new (hour: number, minuter: number): any'. 5 class clock implements ClockConstructor { ~~~~~ PS C:\Users\mingm\Desktop\ts>
出現錯誤
解決,既然不會對靜態的構造方法進行檢查,那就在建立一個接口,進行更進一步的靜態方法的檢查。
即,建立一個接口,返回一個接口,這樣就會對該構造方法進行檢查。
相似於類和父類的關係,子類,父類,超類,超類會返回一個類,會調用超類的構造方法,生成子類,此時在這個過程當中會進行接口的檢查。
// 定義一個用於檢查構造函數的接口,該接口須要返回一個接口 interface ClockConstructor{ new (hour: number, minute: number): ClockInterface; } // 繼續定義一個接口,該接口接收來自上一個接口返回的內容,進行驗證 interface ClockInterface { tick(); } // 建立一個函數,返回一個函數(該函數再次執行) function createClock(ctor: ClockConstructor, hour:number, minute:number):ClockInterface{ return new ctor(hour, minute); } // 定義一個類 class DigitalClock implements ClockInterface { // 下層接口 constructo(h: number, m: number) { }; tick(){ console.log("!!!"); } } // 定義一個類 class AnalogClock implements ClockInterface { constructor(h: number, m: number) { }; tick(){ console.log("!!!!!!!!"); } } // 調用租函數,傳入一個類,返回一個對象 let digital = createClock(DigitalClock, 12, 17); let analog = createClock(AnalogClock, 2, 4);
上方的核心在於建立了兩個接口,一個接口用於檢查父的內容,一個接口用於進行建立對象進行驗證。父的擁有一個函數,傳入一個類,並對其進行檢查。
// 建立一個函數,返回一個函數(該函數再次執行) function createClock(ctor, hour, minute) { return new ctor(hour, minute); // } // 定義一個類 var DigitalClock = /** @class */ (function () { function DigitalClock() { } DigitalClock.prototype.constructo = function (h, m) { }; ; DigitalClock.prototype.tick = function () { console.log("!!!"); }; return DigitalClock; }()); // 定義一個類 var AnalogClock = /** @class */ (function () { function AnalogClock(h, m) { } ; AnalogClock.prototype.tick = function () { console.log("!!!!!!!!"); }; return AnalogClock; }()); // 調用租函數,傳入一個類,返回一個對象 var digital = createClock(DigitalClock, 12, 17); var analog = createClock(AnalogClock, 2, 4); //# sourceMappingURL=out.js.map
// 建立一個函數,返回一個函數(該函數再次執行) function createClock(ctor, hour, minute) { return new ctor(hour, minute); // 此處相似於js中的閉包問題 } // 定義一個類 class DigitalClock { constructo(h, m) { } ; tick() { console.log("!!!"); } } // 定義一個類 class AnalogClock { constructor(h, m) { } ; tick() { console.log("!!!!!!!!"); } } // 調用租函數,傳入一個類,返回一個對象 let digital = createClock(DigitalClock, 12, 17); let analog = createClock(AnalogClock, 2, 4); //# sourceMappingURL=out.js.map
類能繼承,那麼接口也能繼承
// 接口 interface Shape { color: string; } // 一個繼承接口 interface Square extends Shape { sideLength: number; } let square = {} as Square; //類型斷言 square.color = "blue"; square.sideLength = 10;
var square = {}; //類型斷言 square.color = "blue"; square.sideLength = 10; //# sourceMappingURL=out.js.map
也能夠進行從多個接口繼承,即創造出合成接口
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;
var square = {}; square.color = "blue"; square.sideLength = 10; square.penWidth = 5.0; //# sourceMappingURL=out.js.map
對象既可爲函數,又可爲對象
interface Counter { (start: number): string; // 函數 interval: number; reset(): void; } // 下面將會書寫閉包 function getConter():Counter{ // 返回將會是一個接口類型的 let counter = <Counter>function (start: number){}; // 類型斷言 counter.interval = 123; counter.reset = () => { }; return counter; // 返回一個函數 } let c = getConter(); c(10); c.reset(); c.interval = 5.0;
// 下面將會書寫閉包 function getConter() { var counter = function (start) { }; // 類型斷言 counter.interval = 123; counter.reset = function () { }; return counter; // 返回一個函數 } var c = getConter(); c(10); c.reset(); c.interval = 5.0; //# sourceMappingURL=out.js.map
接口繼承類時,會繼承類成員,但不包含其實現。
即,接口聲明瞭類中的成員,但並無提供具體的實現。
接口一樣會繼承private(私有的),和protected(對於本包和子一樣可見)
根據上述的說明,能夠知道,當一個接口,繼承自擁有protected的類的時候,此時該接口只能被子類,或者該類使用。
class Control { private state: any; // 定義一個任何類型的私有屬性 } // 定義一個接口,該接口繼承自Control interface SelectableControl extends Control { select(): void; } // 定義一個子類,該類繼承自Control,並使用接口SelectableControl,因爲是子類,可使用SelectableControl接口 class Button extends Control implements SelectableControl { select() { }; } // 定義一個子類該類繼承自Control class TextBox extends Control { select(){} } // 定義一個Image類,該類不能使用SelectableControl接口 //class Image implements SelectableControl{ //} // 和其他類沒有任何繼承關係的類 class Liaction { }
es5 js以下
var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); } return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var Control = /** @class */ (function () { function Control() { } return Control; }()); // 定義一個子類,該類繼承自Control,並使用接口SelectableControl,因爲是子類,可使用SelectableControl接口 var Button = /** @class */ (function (_super) { __extends(Button, _super); function Button() { return _super !== null && _super.apply(this, arguments) || this; } Button.prototype.select = function () { }; ; return Button; }(Control)); // 定義一個子類該類繼承自Control var TextBox = /** @class */ (function (_super) { __extends(TextBox, _super); function TextBox() { return _super !== null && _super.apply(this, arguments) || this; } TextBox.prototype.select = function () { }; return TextBox; }(Control)); // 定義一個Image類,該類不能使用SelectableControl接口 //class Image implements SelectableControl{ //} // 和其他類沒有任何繼承關係的類 var Liaction = /** @class */ (function () { function Liaction() { } return Liaction; }()); //# sourceMappingURL=out.js.map
PS C:\Users\mingm\Desktop\ts> tsc Active code page: 65001 PS C:\Users\mingm\Desktop\ts>
es6以下
class Control { } // 定義一個子類,該類繼承自Control,並使用接口SelectableControl,因爲是子類,可使用SelectableControl接口 class Button extends Control { select() { } ; } // 定義一個子類該類繼承自Control class TextBox extends Control { select() { } } // 定義一個Image類,該類不能使用SelectableControl接口 //class Image implements SelectableControl{ //} // 和其他類沒有任何繼承關係的類 class Liaction { } //# sourceMappingURL=out.js.map