TypeScript基礎入門之高級類型的交叉類型和聯(lián)合類型

轉(zhuǎn)發(fā)

TypeScript基礎入門之高級類型的交叉類型和聯(lián)合類型

項目實踐倉庫

https://github.com/durban89/typescript_demo.git
tag: 1.4.2

為了保證后面的學習演示需要安裝下ts-node,這樣后面的每個操作都能直接運行看到輸出的結(jié)果。

npm install -D ts-node

后面自己在練習的時候可以這樣使用

npx ts-node 腳本路徑

高級類型

交叉類型(Intersection Types)

交叉類型是將多個類型合并為一個類型。 這讓我們可以把現(xiàn)有的多種類型疊加到一起成為一種類型,它包含了所需的所有類型的特性。 例如, Person & Serializable & Loggable同時是 Person 和 Serializable 和 Loggable。 就是說這個類型的對象同時擁有了這三種類型的成員。您將主要看到用于mixins的交集類型和其他不適合經(jīng)典面向?qū)ο竽>叩母拍?。(在JavaScript中有很多這些?。┻@是一個簡單的例子,展示了如何創(chuàng)建mixin:

function extend<T, U>(first: T, second: U): T & U {
    let result = <T & U>{}

    for (let id in first) {
        (<any>result)[id] = (<any>first)[id];
    }

    for (let id in second) {
        if (!result.hasOwnProperty(id)) {
            (<any>result)[id] = (<any>second)[id];
        }
    }

    return result
} 

class AdvancedTypesClass {
    constructor(public name: string){}
}

interface LoggerInterface {
    log(): void;
}

class AdvancedTypesLoggerClass implements LoggerInterface {
    log(): void {
        console.log('console logging');
    }
}

var logger = new AdvancedTypesLoggerClass();

var extend1 = extend(new AdvancedTypesClass("string"), new AdvancedTypesLoggerClass());
var e = extend1.name;
console.log(e);
extend1.log();

編譯運行,注意這里要編譯運行,我使用ts-node已經(jīng)不能運行成功了??赡苁悄睦锱渲玫挠袉栴},具體步驟如下。

tsc ./src/advanced_types_1.ts
$ node ./src/advanced_types_1.js
string
console logging

聯(lián)合類型(Union Types)

聯(lián)合類型與交叉類型很有關聯(lián),但是使用上卻完全不同。 偶爾你會遇到這種情況,一個代碼庫希望傳入 number或 string類型的參數(shù)。 例如下面的函數(shù):

/**
 * 為給定的字符串左側(cè)添加"padding"
 * 如果"padding"是一個字符串,則添加將字符串添加到給定字符串的左側(cè)
 * 如果"padding"是一個數(shù)字,則添加padding個數(shù)量的空格到給定字符串的左側(cè)
 */
function padLeft(value: string, padding: any) {
    if (typeof padding === 'string') {
        return padding + value;
    }

    if (typeof padding === 'number') {
        return Array(padding + 1).join(' ') + value;
    }

    throw new Error(`Excepted string or number, got ${padding}`);
}
console.log("|" + padLeft("string", 4) + "|");
console.log("|" + padLeft("string", "a") + "|");

編譯并運行后得到如下結(jié)果

$ tsc ./src/advanced_types_1.ts && node ./src/advanced_types_1.js
|    string|
|astring|

padLeft有一個問題,就是padding這個參數(shù)是一個any類型,那就意味著我們可以在傳遞參數(shù)的時候,參數(shù)的類型可以是number或者是string,而TypeScript將會正常解析,
如果如下的方式調(diào)用,編譯的時候是可以正常解析的,但是運行的時候回報錯

padLeft("Hello world", true);

在傳統(tǒng)的面向?qū)ο笳Z言里,我們可能會將這兩種類型抽象成有層級的類型。 這么做顯然是非常清晰的,但同時也存在了過度設計。 padLeft原始版本的好處之一是允許我們傳入原始類型。 這樣做的話使用起來既簡單又方便。 如果我們就是想使用已經(jīng)存在的函數(shù)的話,這種新的方式就不適用了。除了any, 我們可以使用"聯(lián)合類型"做為padding的參數(shù),如下:

/**
 * 為給定的字符串左側(cè)添加"padding"
 * 如果"padding"是一個字符串,則添加將字符串添加到給定字符串的左側(cè)
 * 如果"padding"是一個數(shù)字,則添加padding個數(shù)量的空格到給定字符串的左側(cè)
 */
function padLeft(value: string, padding: string | number) {
    if (typeof padding === 'string') {
        return padding + value;
    }

    if (typeof padding === 'number') {
        return Array(padding + 1).join(' ') + value;
    }

    throw new Error(`Excepted string or number, got ${padding}`);
}
console.log("|" + padLeft("string", 4) + "|");
console.log("|" + padLeft("string", "a") + "|");
console.log("|" + padLeft("string", true) + "|");

編譯并運行后得到如下結(jié)果

$ tsc ./src/advanced_types_1.ts && node ./src/advanced_types_1.js
src/advanced_types_1.ts:65:37 - error TS2345: Argument of type 'true' is not assignable to parameter of type 'string | number'.

65 console.log("|" + padLeft("string", true) + "|");

從實例演示可以看出,當傳入一個boolean類型值的時候,在編輯的時候TypeScript就做出了判斷,表示boolean類型的參數(shù)不被支持

聯(lián)合類型表示一個值可以是幾種類型之一。 我們用豎線(|)分隔每個類型,所以 number | string | boolean表示一個值可以是 number, string,或 boolean。

如果一個值是聯(lián)合類型,我們只能訪問此聯(lián)合類型的所有類型里共有的成員,如下實例

interface Type1 {
    func1(): void;
    func2(): void;
}

interface Type2 {
    func3(): void;
    func2(): void;
}

class Type1Class implements Type1 {
    func1(): void {
        console.log('func1 run');
    }

    func2(): void {
        console.log('func2 run');
    }
}

class Type2Class implements Type2 {
    func3(): void {
        console.log('func1 run');
    }

    func2(): void {
        console.log('func2 run');
    }
}

function getSomeType(type: string): Type1Class | Type2Class {
    if (type === '1') {
        return new Type1Class();
    }

    if (type === '2') {
        return new Type2Class();
    }

    throw new Error(`Excepted Type1Class or Type2Class, got ${type}`);
}

let type = getSomeType('1');
type.func2();
type.func1(); // 報錯

編譯并運行后得到如下結(jié)果

$ tsc ./src/advanced_types_1.ts
src/advanced_types_1.ts:111:6 - error TS2551: Property 'func1' does not exist on type 'Type1Class | Type2Class'. Did you mean 'func2'?
  Property 'func1' does not exist on type 'Type2Class'.

111 type.func1();

這里的聯(lián)合類型可能有點復雜,但是你很容易就習慣了。 如果一個值的類型是 A | B,我們能夠 確定的是它包含了 A 和 B中共有的成員。 這個例子里, Type1Class具有一個func1成員。 我們不能確定一個 Type1Class | Type2Class類型的變量是否有func1方法。 如果變量在運行時是Type1Class類型,那么調(diào)用type.func1()就出錯了。

本實例結(jié)束實踐項目地址

https://github.com/durban89/typescript_demo.git
tag: 1.4.3
?著作權(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)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,695評論 19 139
  • TypeScript 是 JavaScript 的一個超集,主要提供了類型系統(tǒng)和對 ES6 的支持,它由 Micr...
    Gukson666閱讀 8,916評論 3 29
  • 轉(zhuǎn)載地址 TypeScript基礎入門 - 基礎類型 項目實踐倉庫 為了保證后面的學習演示需要安裝下ts-node...
    鵬鯤云之上閱讀 571評論 0 1
  • 20170904(07/30)
    同在我心閱讀 300評論 3 7
  • 我一直在感謝這個時代,因為經(jīng)濟上的富有,讓我有更多的時間去陪伴老二的成長,因此我就有條件去從事我這份當母親的事業(yè)了...
    精致典雅閱讀 538評論 0 0

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