Typescript入門之:接口

typescript基本使用筆記


安裝typescript

npm install -g typescript 全局安裝ts

tsc *.ts 編譯ts文件編譯成js文件,如果ts有語法錯誤,則會編譯報錯,但是仍然會創(chuàng)建編譯好的js文件并且編譯執(zhí)行


基礎類型

定義變量或者參數(shù)的時候通過 :號指定類型

  • boolean 布爾型

  • number 數(shù)字型:包括各種進制的數(shù)值型,浮點型

  • string 字符串類型:可以使用模板字符串

  • number[]/Array<number> 數(shù)組類型:寫法有兩種一種是number后面加[],一種是通過數(shù)組Array 泛型

  • tuple :一個已知元素長度和類型的數(shù)組,且類型不能重復,屬于聯(lián)合類型

  • enum 枚舉類型:使用枚舉類型可以為一組數(shù)值賦予友好的名字,一種類似數(shù)組的引用類型形式,可以通過下標訪問和賦值,也可以指定下標

  • any :任意類型,不會進行類型檢查,任意類型都可以通過,可以組和,比如 any[]表示任意元素類型的數(shù)組

  • void : 空類型,通常用來表示無返回值,只能夠賦值為:undefined和null

  • null和undefined :默認是所有類型的子集,意思是所有其他類型都可以賦值成null和undefined類型

  • never :不應該運行到此處的類型,

  • object :非原始類型,除了string,number,boolean,null,undefined,symbol這幾個js的基本類型

  • 類型斷言(類型轉(zhuǎn)換):語法為 let someValue :any = 'Word' 可以強行將右邊轉(zhuǎn)為左邊 ;另一個方法是'as'語法,let strLength: number = (someValue as string).length;


變量聲明

  • let和var的區(qū)別(略)

  • 解構(gòu) --快速的變量賦值


    //---------------數(shù)組解構(gòu)---------------------

    // 數(shù)組解構(gòu)
    let input = [1, 2];
    let [first, second] = input;
    console.log(first); // outputs 1
    console.log(second); // outputs 2

    //剩余變量的數(shù)組解構(gòu)
    let [first, ...rest] = [1, 2, 3, 4];
    console.log(first); // outputs 1
    console.log(rest); // outputs [ 2, 3, 4 ]

    //對應下標的數(shù)組解構(gòu)
    let [, second, , fourth] = [1, 2, 3, 4];

    //------------------對象解構(gòu)---------------

    let o = {
        a: "foo",
        b: 12,
        c: "bar"
    };
    let { a, b } = o;
    //快速的將o對應的鍵值賦給a,b

    let { a, ...passthrough } = o;
    let total = passthrough.b + passthrough.c.length;
    //剩余變量的對象解構(gòu)

    let { a: newName1, b: newName2 } = o;
    //變量重命名,此處相當于{a,b}=0  newName1 = a,newName2 = b;
    //此處的:相當于賦值符號
    //為什么這里的:不是類型聲明符號?
    //因為:解構(gòu)時如果需要類型聲明需要完整的寫類型模式
    //例如:let {a, b}: {a: string, b: number} = o;


    function keepWholeObject(wholeObject: { a: string, b?: number }) {
        let { a, b = 1001 } = wholeObject;
        //解構(gòu)時的默認值,如果不存在b這個鍵值時,b=1001
    }


    //--------------函數(shù)聲明-----------------------
    
    
    type C = { a: string, b?: number }
    function f({ a, b }: C): void {
        // ...
    }
    //將解構(gòu)元素當作參數(shù)傳遞


    function f({ a="", b=0 } = {}): void {
        // ...
    }
    f();
    //解構(gòu)傳參帶默認值


    function f({ a, b = 0 } = { a: "" }): void {
        // ...
    }
    f({ a: "yes" }); // ok, default b = 0
    f(); // ok, default to {a: ""}, which then defaults b = 0
    f({}); // error, 'a' is required if you supply an argument
    //解構(gòu)+默認賦值,默認傳入{a:""}如果啥也不傳,默認參數(shù)為{a:''},那么a='',b=0



  • 展開 --與解構(gòu)相反將數(shù)組展開或者將對象展開


    //所有的展開都是淺拷貝?。?
    //將數(shù)組展開并且插入新數(shù)組
    let first = [1, 2];
    let second = [3, 4];
    let bothPlus = [0, ...first, ...second, 5];

    //將對象展開
    let defaults = { food: "spicy", price: "$$", ambiance: "noisy" };
    let search = { ...defaults, food: "rich" }; 

    //對象展開會丟失對象方法
    class C {
    p = 12;
    m() {
    }
    }
    let c = new C();
    let clone = { ...c };
    clone.p; // ok
    clone.m(); // error!

接口

  • 接口的作用就是為這些類型命名和代碼進行綁定,接口一般用來做函數(shù)參數(shù)的預定義

  • 關鍵字 interface

    interface LabelledValue {
        //定義一個接口
        label: string;
        //接口中定義了label這個字段必須是字符串類型
    }

    function printLabel(labelledObj: LabelledValue) {
        //參數(shù)labelledObj 套用這個接口,所以參數(shù)必須有l(wèi)abel字段并且為string類型
        console.log(labelledObj.label);
    }

    let myObj = {size: 10, label: "Size 10 Object"};
    printLabel(myObj);
  • 可選參數(shù)接口

interface SquareConfig {
  color?: string;   //只是在類型聲明符前面增加了一個問號
  width?: number;
}
  • 只讀屬性

    只能在對象剛創(chuàng)建的時候?qū)ζ渲颠M行修改,可以在屬性名前面增加readonly來指定只讀屬性

  • 額外的屬性檢查

interface SquareConfig {
    color?: string;
    width?: number;
    [propName: string]: any;
    //使用propName內(nèi)置屬性獲取接口的其他參數(shù)傳值,并且對其進行單獨的檢查
}
  • 函數(shù)類型 接口也能用來描述函數(shù)類型

interface SearchFunc {
  (source: string, subString: string): boolean;
  //定義了一個函數(shù)接口,參數(shù)為source和substring類型為string類型,返回值為boolean類型
}

//以下兩種調(diào)用方式都符合邏輯
let mySearch: SearchFunc;
mySearch = function(source: string, subString: string) {
  let result = source.search(subString);
  return result > -1;
}

let mySearch: SearchFunc;
mySearch = function(src: string, sub: string): boolean {
  let result = src.search(sub);
  return result > -1;
}
  • 可索引的類型 可以自定義接口用來限定可索引類型的類型解構(gòu)


    //基礎的引用類型接口
    interface StringArray {
    [index: number]: string;
    //定義一個索引類型的接口:
    //":"左邊表示索引的類型定義,右邊表示值的類型定義
    //所以上面的意思是定義了一個索引類型的接口,index必須是number類型,值必須是string類型


    //嵌套設計
    interface NumberDictionary {
        [index: string]: number;
        //定義了該索引類型的index是string類型,值是number類型
        length: number;    // 可以,length是number類型
        //legth字段定義成number類型,length也屬于該索引類型的index,其值也要是number類型
        name: string       // 錯誤,`name`的類型與索引類型返回值的類型不匹配
        //同理,name也是index,該值也必須是number類型
        }
    }

    let myArray: StringArray;
    myArray = ["Bob", "Fred"];

    let myStr: string = myArray[0];

    //只讀索引的接口設計
    interface ReadonlyStringArray {
        readonly [index: number]: string;
        //設定index的類型為只讀類型,值為string類型
    }
    let myArray: ReadonlyStringArray = ["Alice", "Bob"];
    //由于設置了index的只讀類型,所以無法進行修改
    myArray[2] = "Mallory"; // error!


  • 類類型 與C#或Java里接口的基本作用一樣,TypeScript也能夠用它來明確的強制一個類去符合某種契約。

interface ClockInterface {
    currentTime: Date;
    //定義了一個類型型的接口,其currentTime屬性必須是一個Date類型
}

class Clock implements ClockInterface {
    currentTime: Date;
    constructor(h: number, m: number) { }
}



//類類型使用方法如下

interface ClockInterface {
    currentTime: Date;
    setTime(d: Date);
}

class Clock implements ClockInterface {
    //implements為關鍵字,表示該類使用ClockInterface這個接口
    currentTime: Date;
    setTime(d: Date) {
        this.currentTime = d;
    }
    constructor(h: number, m: number) { }
}

//類靜態(tài)部分和實例部分的區(qū)別
interface ClockConstructor {
    new (hour: number, minute: number);
}

class Clock implements ClockConstructor {
    currentTime: Date;
    constructor(h: number, m: number) { }
    //constructor構(gòu)造函數(shù)里面的參數(shù)為類的靜態(tài)屬性所以不會適用上面那個接口的檢測方法
}



//--------------------復雜的類類型例子--------------------------------------
interface ClockConstructor {
    new (hour: number, minute: number): ClockInterface;
}
interface ClockInterface {
    tick();
}

function createClock(ctor: ClockConstructor, hour: number, minute: number): 
//聲明一個函數(shù)
//函數(shù)的參數(shù)接口定義是 ctor的接口是ClockConstructor,hour是number類型,minute是number
//ClockConstructor又是一個函數(shù)接口,表示構(gòu)造函數(shù)參數(shù)hour和minute的類型都是number,且必須具有屬性ClockInterface接口,也就是必須有這個tick屬性或者方法
//通過這樣嵌套,達到對構(gòu)造函數(shù)靜態(tài)參數(shù)的接口定義
ClockInterface {
//函數(shù)的返回值是ClockInterface這個接口定義的,必須有tick這個屬性或者方法
    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);
  • 接口的繼承 和類一樣,接口也可以相互繼承。 這讓我們能夠從一個接口里復制成員到另一個接口里,可以更靈活地將接口分割到可重用的模塊里。

interface Shape {
    color: string;
}

interface Square extends Shape {
    //關鍵字extend Square繼承自Shape
    sideLength: number;
}

let square = <Square>{};
square.color = "blue";
square.sideLength = 10;


// 一個接口可以繼承多個接口,創(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;
  • 混合類型 一個接口可以同時擁有多種類型接口的特性,實現(xiàn)該接口的多類型

interface Counter {
    //定義一個接口Counter
    (start: number): string;
    //擁有函數(shù)接口類型的特性,定義了參數(shù)和返回值的類型
    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;
  • 接口繼承類 當一個接口繼承一個類,會繼承其類的成員,但是不包括其實現(xiàn),


class Control {
    private state: any;
}

interface SelectableControl extends Control {
    //該接口繼承自類Control,所以也會繼承其屬性,包括私有屬性
    //所以再次使用該接口的時候,會繼承該私有屬性的定義
    select(): void;
}

class Button extends Control implements SelectableControl {
    select() { }
}

class TextBox extends Control {
    select() { }
}

// 錯誤:“Image”類型缺少“state”屬性。
class Image implements SelectableControl {
    select() { }
}

class Location {

}
//在上面的例子里,SelectableControl包含了Control的所有成員,包括私有成員state。 因為 state是私有成員,所以只能夠是Control的子類們才能實現(xiàn)SelectableControl接口。 因為只有 Control的子類才能夠擁有一個聲明于Control的私有成員state,這對私有成員的兼容性是必需的。

//在Control類內(nèi)部,是允許通過SelectableControl的實例來訪問私有成員state的。 實際上, SelectableControl接口和擁有select方法的Control類是一樣的。 Button和TextBox類是SelectableControl的子類(因為它們都繼承自Control并有select方法),但Image和Location類并不是這樣的。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • typescript現(xiàn)在已經(jīng)慢慢變成前端工程師必學必會的技能了,它在開發(fā)大型應用的時候可以讓產(chǎn)品更加可控,本篇就試...
    大喵愛讀書閱讀 4,417評論 0 5
  • 概述 TypeScript本質(zhì)上是向JavaScript語言添加了可選的靜態(tài)類型和基于類的面向?qū)ο缶幊蹋瑫r也支持...
    oWSQo閱讀 8,690評論 1 45
  • 基礎類型 布爾 let is:boolean = false 數(shù)字 let n:number = 6 let n:...
    泡沫的快樂閱讀 1,341評論 0 0
  • 關于TypeScript TypeScript是JavaScript的超集,主要提供類型系統(tǒng)和對ES6的支持,由M...
    kim_jin閱讀 823評論 0 1
  • 基于2018年Stack Overflow Developer的調(diào)研,TypeScript作為編程語言比JavaS...
    Ming_Hu閱讀 2,407評論 1 33

友情鏈接更多精彩內(nèi)容