TypeScript
接口
接口只讀屬性
使用關(guān)鍵字readonly定義只讀的接口屬性
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; // 該句錯誤疑务,不能進行賦值操作
出現(xiàn)錯誤宝与,如下
創(chuàng)建不可修改的數(shù)組
// 定義一個接口
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; // 設(shè)置為只讀的數(shù)組
ro[0] = 12; // 不可進行賦值捉捅。出現(xiàn)賦值錯誤
如果想要重新賦值撤防,斷言重寫
當(dāng)一個值有多個類型的時候,使用斷言重寫棒口,確定一個新的類型
// 定義一個接口
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
類型斷言很大程度上可以規(guī)范類型
函數(shù)類型的接口
// 定義一個函數(shù)類型的接口
interface SearchFunc {
(source: string, subString: string): boolean; // 定義一個函數(shù)類型的接口
}
// 使用這個接口
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
編譯器會逐個檢查,如果統(tǒng)統(tǒng)正確茎毁,則編譯通過克懊,否則編譯不通過
定義索引接口
// 定義索引接口
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
索引值內(nèi)部必須全部為number類型的
// 定義接口,一個索引值類型的保檐,其返回值也為索引類型的
interface NumberDictionary{
[index: string]: number;
length: number; // 可以設(shè)置length
name: string; // 錯誤索引值內(nèi)部不能擁有string類型
}
編譯一下出現(xiàn)錯誤
索引簽名依舊可以設(shè)置為只讀耕蝉,此時可以防止給索引賦值。使用關(guān)鍵字readonly
// 定義接口
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 關(guān)鍵字clock類符合接口clockInterFace
currentTime: Date;
constructor(h:number, m:number){
// 定義構(gòu)造函數(shù)
}
}
// 注意在上方中并不會對靜態(tài)的夜只,進行檢查垒在。只會對非靜態(tài)的部分,即非構(gòu)造函數(shù)部分進行檢查
var Clock = /** @class */ (function () {
function Clock(h, m) {
// 定義構(gòu)造函數(shù)
}
return Clock;
}());
//# sourceMappingURL=out.js.map
如果配置成為es6即
{
"compilerOptions": {
"out": "built/out.js",
"sourceMap": true,
"target": "es6"
},
"files": [
"greeter.ts"
]
}
class Clock {
constructor(h, m) {
// 定義構(gòu)造函數(shù)
}
}
//# sourceMappingURL=out.js.map
接口描述方法扔亥,類實現(xiàn)
interface ClockInterface {
currentTime: Date;
setTime(d: Date); // 定義接口的方法
}
class Clock implements ClockInterface{
currentTime: Date; // 接口檢查的
setTime(d:Date){ // 接口檢查的方法
this.currentTime = d;
}
constructor(h:number, m:number){ // 接口不會檢查靜態(tài)的構(gòu)造方法
}
}
var Clock = /** @class */ (function () {
function Clock(h, m) {
}
Clock.prototype.setTime = function (d) {
this.currentTime = d;
};
return Clock;
}());
//# sourceMappingURL=out.js.map
關(guān)于構(gòu)造函數(shù)的接口
構(gòu)造函數(shù)屬于靜態(tài)的方法场躯,當(dāng)構(gòu)造器定義了一個靜態(tài)的方法的時候。構(gòu)造器只檢查動態(tài)的方法旅挤,并不會檢查動態(tài)的方法踢关,故,下方的寫法編譯器不通過
interface ClockConstructor {
new (hour: number, minuter: number); // 定義構(gòu)造函數(shù)的接口
};
class clock implements ClockConstructor {
currenTime: Date;
constructor(h:number, m:number){ // 接口限制的是此構(gòu)造函數(shù)
}
}interface ClockConstructor {
new (hour: number, minuter: number); // 定義構(gòu)造函數(shù)的接口
};
class clock implements ClockConstructor {
currenTime: Date;
constructor(h:number, m:number){ // 接口限制的是此構(gòu)造函數(shù)
}
}interface ClockConstructor {
new (hour: number, minuter: number); // 定義構(gòu)造函數(shù)的接口
};
class clock implements ClockConstructor {
currenTime: Date;
constructor(h:number, m:number){ // 接口限制的是此構(gòu)造函數(shù)
}
}interface ClockConstructor {
new (hour: number, minuter: number); // 定義構(gòu)造函數(shù)的接口
};
class clock implements ClockConstructor {
currenTime: Date;
constructor(h:number, m:number){ // 接口限制的是此構(gòu)造函數(shù)
}
}interface ClockConstructor {
new (hour: number, minuter: number); // 定義構(gòu)造函數(shù)的接口
};
class clock implements ClockConstructor {
currenTime: Date;
constructor(h:number, m:number){ // 接口限制的是此構(gòu)造函數(shù)
}
}interface ClockConstructor {
new (hour: number, minuter: number); // 定義構(gòu)造函數(shù)的接口
};
class clock implements ClockConstructor {
currenTime: Date;
constructor(h:number, m:number){ // 接口限制的是此構(gòu)造函數(shù)
}
}
編譯
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>
出現(xiàn)錯誤
解決粘茄,既然不會對靜態(tài)的構(gòu)造方法進行檢查签舞,那就在創(chuàng)建一個接口,進行更進一步的靜態(tài)方法的檢查柒瓣。
即儒搭,創(chuàng)建一個接口,返回一個接口芙贫,這樣就會對該構(gòu)造方法進行檢查搂鲫。
類似于類和父類的關(guān)系,子類磺平,父類魂仍,超類,超類會返回一個類拣挪,會調(diào)用超類的構(gòu)造方法擦酌,生成子類,此時在這個過程中會進行接口的檢查菠劝。
// 定義一個用于檢查構(gòu)造函數(shù)的接口仑氛,該接口需要返回一個接口
interface ClockConstructor{
new (hour: number, minute: number): ClockInterface;
}
// 繼續(xù)定義一個接口,該接口接收來自上一個接口返回的內(nèi)容闸英,進行驗證
interface ClockInterface {
tick();
}
// 創(chuàng)建一個函數(shù),返回一個函數(shù)(該函數(shù)再次執(zhí)行)
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("=橥唷8巍!");
}
}
// 定義一個類
class AnalogClock implements ClockInterface {
constructor(h: number, m: number) { };
tick(){
console.log("!!!!!!!!");
}
}
// 調(diào)用租函數(shù)遇伞,傳入一個類辙喂,返回一個對象
let digital = createClock(DigitalClock, 12, 17);
let analog = createClock(AnalogClock, 2, 4);
上方的核心在于創(chuàng)建了兩個接口,一個接口用于檢查父的內(nèi)容,一個接口用于進行創(chuàng)建對象進行驗證巍耗。父的擁有一個函數(shù)秋麸,傳入一個類,并對其進行檢查炬太。
// 創(chuàng)建一個函數(shù)灸蟆,返回一個函數(shù)(該函數(shù)再次執(zhí)行)
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("!G鬃濉炒考!");
};
return DigitalClock;
}());
// 定義一個類
var AnalogClock = /** @class */ (function () {
function AnalogClock(h, m) {
}
;
AnalogClock.prototype.tick = function () {
console.log("!!!!!!!!");
};
return AnalogClock;
}());
// 調(diào)用租函數(shù),傳入一個類霎迫,返回一個對象
var digital = createClock(DigitalClock, 12, 17);
var analog = createClock(AnalogClock, 2, 4);
//# sourceMappingURL=out.js.map
// 創(chuàng)建一個函數(shù)斋枢,返回一個函數(shù)(該函數(shù)再次執(zhí)行)
function createClock(ctor, hour, minute) {
return new ctor(hour, minute); // 此處類似于js中的閉包問題
}
// 定義一個類
class DigitalClock {
constructo(h, m) { }
;
tick() {
console.log("!V瓤帚!");
}
}
// 定義一個類
class AnalogClock {
constructor(h, m) { }
;
tick() {
console.log("!!!!!!!!");
}
}
// 調(diào)用租函數(shù),傳入一個類涩赢,返回一個對象
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
也可以進行從多個接口繼承,即創(chuàng)造出合成接口
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
混合類型
對象既可為函數(shù)谒主,又可為對象
interface Counter {
(start: number): string; // 函數(shù)
interval: number;
reset(): void;
}
// 下面將會書寫閉包
function getConter():Counter{ // 返回將會是一個接口類型的
let counter = <Counter>function (start: number){}; // 類型斷言
counter.interval = 123;
counter.reset = () => { };
return counter; // 返回一個函數(shù)
}
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; // 返回一個函數(shù)
}
var c = getConter();
c(10);
c.reset();
c.interval = 5.0;
//# sourceMappingURL=out.js.map
接口繼承類
接口繼承類時朝扼,會繼承類成員,但不包含其實現(xiàn)霎肯。
即擎颖,接口聲明了類中的成員,但并沒有提供具體的實現(xiàn)观游。
接口同樣會繼承private(私有的)搂捧,和protected(對于本包和子同樣可見)
根據(jù)上述的說明,可以知道懂缕,當(dāng)一個接口允跑,繼承自擁有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{
//}
// 和其余類沒有任何繼承關(guān)系的類
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{
//}
// 和其余類沒有任何繼承關(guān)系的類
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{
//}
// 和其余類沒有任何繼承關(guān)系的類
class Liaction {
}
//# sourceMappingURL=out.js.map