溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

從C#到TypeScript - 高級(jí)類型

發(fā)布時(shí)間:2020-04-06 14:47:29 來源:網(wǎng)絡(luò) 閱讀:215 作者:張立達(dá) 欄目:網(wǎng)絡(luò)安全

C# vs TypeScript - 高級(jí)類型

上一篇講了基礎(chǔ)類型,基本上用基礎(chǔ)類型足夠開發(fā)了,不過如果要更高效的開發(fā),還是要看下高級(jí)類型,這篇和C#共同點(diǎn)并不多,只是延用這個(gè)主題。

聯(lián)合類型

可以從字面上進(jìn)行理解:其實(shí)就是多個(gè)類型聯(lián)合在一起,用|符號(hào)隔開。
如: string | number, 表示希望這個(gè)類型既可以是string,又可以是number
聯(lián)合類型的字段只能調(diào)用這些類型共同擁有的方法,除非類型推論系統(tǒng)自動(dòng)判斷出真正的類型。

//這里sn就是一個(gè)聯(lián)合類型的字段,由于類型推論推斷出sn肯定是string,所以sn可以調(diào)用string的所有方法let sn: string | number = 'string, number';//這里就推斷不出具體的類型,只能調(diào)用toString, toValue了function snFunc(): string | number{    return 'string, number';
}

聯(lián)合類型不光是可以聯(lián)合基本類型,也可以是用戶自定義的class, interace等。

交叉類型

|就有&,交叉類型就是用&符號(hào)隔開,表示把多個(gè)類型合在一起,新類型包含所有類型的功能。
一些語言如Python有mixins功能,用這個(gè)就很容易做到,主要是類似多重繼承,不過個(gè)人不是用喜歡這個(gè),明顯違反了單一原則。
下面這段代碼就顯示了mixins結(jié)合兩個(gè)類的功能,看起來是不是有點(diǎn)不大合理,目前的趨勢也是組合優(yōu)先,用組合同樣也可以做到這些。

class Person {

    talk(): string {        return `一個(gè)人`;
    }
}class Dog {

    bark(): string {        return '汪汪汪';
    }
}function extend<T, U>(first: T, second: U): T & U {    let result = <T & U>{};    for (let func of Object.getOwnPropertyNames(Object.getPrototypeOf(first))) {
        (<any>result)[func] = (<any>first)[func];
    }    for (let func of Object.getOwnPropertyNames(Object.getPrototypeOf(second))) {
        (<any>result)[func] = (<any>second)[func];
    }    return result;
}let personDog = extend(new Person(), new Dog());console.info(personDog.talk());console.info(personDog.bark());

類型轉(zhuǎn)換

C#里常用的類型轉(zhuǎn)換一個(gè)是前面圓括號(hào)加類型,一個(gè)是as
TypeScript和C#一樣,只不是圓括號(hào)改成尖括號(hào)。

let test: any = '123';let str1: string = <string>test;let str2: string = test as string;

類型保護(hù)

聯(lián)合類型返回的是多個(gè)類型的其中一個(gè),但是用的時(shí)候并不知道是哪個(gè),需要一個(gè)一個(gè)判斷,這顯得很麻煩。

function get(): number | string{    return 'test';
}let test = get();var len = test.length; //編譯不了,不知道test到底是number還是stringlet str = '';if((<string>test).sub){    // string} else {    // number}

除了通過是否有string特有的方法來判斷是否是string,也可以用類似C#的typeof來得到它的類型,而且重要的是會(huì)提供類型保護(hù)機(jī)制,
即在typeof作用域里會(huì)知道這個(gè)變量的類型。

function get(): number | string{    return 'test';
}let test = get();if(typeof test === 'string'){    console.info(test.length); // 這里由于typeof確定了test類型是string,所以作用域內(nèi)可以直接取length,而不用<string>轉(zhuǎn)一次}

typeof比較是有限制的,自己創(chuàng)建的類返回的都是object,這時(shí)會(huì)用到instanceof,并且instanceof同樣會(huì)提供類型保護(hù)機(jī)制。
另外還有類型斷言可以提供類似的功能,不過不如上面的來得方便。

function get(): number | string{    return 'test';
}let test = get();function isStr(p : number | string): p is string{    return (<string>p).sub !== 'undefined';
}if(isStr(test)) {    console.info(test.length);
} else {    console.info(test + 1);
}

上面p is string就是斷言參數(shù)pstring類型,從而在isStr后可以自動(dòng)得到test的類型,并且在else里也知道是number類型。

這點(diǎn)上比C#來得好,一般C#做法可能是用as操作符轉(zhuǎn)過來,然后判斷是否為空,如果類型多操作起來也很復(fù)雜。

類型別名

類型別名即可以為現(xiàn)有類型取一個(gè)新名字。

type newstring = string;let str: newstring = 'aaa';console.info(str.length);

在C#中也可以用using strList = System.Generic.List做個(gè)別名,不過還是不一樣,C#的是可以實(shí)例化的。
TypeScript別名不是新建一個(gè)類型,而是現(xiàn)有類型的一個(gè)引用。
給現(xiàn)在類型起別名意義不大,倒是可以配合聯(lián)合類型或交叉類型做成一些可讀的或比較新穎的類型。
別名也支持泛型,現(xiàn)在就有一個(gè)用別名創(chuàng)建了一個(gè)Tree類型,不過也只是別名,不能實(shí)例化,只能是看的,這點(diǎn)不如接口實(shí)在。

class Chicken{}class Duck{}type Fowl = Chicken | Duck;type Tree<T> = {
    value: T;
    left: Tree<T>;
    right: Tree<T>;
}

字符串字面量類型

TypeScript可以讓string成為一個(gè)類型,比如let strType = 'string type'。
這個(gè)可以用在方法參數(shù)中,用來限制參數(shù)的輸入。

function test(param1: 'test1' | 'test2' | 'test3'){

}
test('test'); // 編譯不了,參數(shù)只能是test1, test2或test3

可辨識(shí)聯(lián)合

綜合上面的字符串字面量類型、聯(lián)合類型、類型保護(hù)、類型別名可以創(chuàng)建一個(gè)可辨識(shí)聯(lián)合的模式。
必須要在自定義的多個(gè)類中有相同的字段,這個(gè)字段用的是字符串字面量類型并且把這些類型聯(lián)合起來。

interface Square {
    kind: "square";
    size: number;
}interface Rectangle {
    kind: "rectangle";
    width: number;
    height: number;
}interface Circle {
    kind: "circle";
    radius: number;
}type Shape = Square | Rectangle | Circle;// 這里就可以用可辨識(shí)聯(lián)合function area(s: Shape) {    switch (s.kind) {        case "square": return s.size * s.size;        case "rectangle": return s.height * s.width;        case "circle": return Math.PI * s.radius ** 2;
    }
}

類型推論

TypeScript可以根據(jù)賦值或上下文推論出變量的類型,所以有時(shí)可以不用明確標(biāo)明變量或函數(shù)返回值的類型。

let x = 123; // 這里能推論出x是number,就不用寫成這樣: let x: number = 123;function get(){ 
    return [1, 2, 3];
}let arr = get(); // 這里也能推論出arr是number[];function get(){    return [1, '2', 3];
}let arr = get(); // 這里能推論出arr是(number | string)[];

不過個(gè)人覺得除了一些很明顯的let x = 123之類可以不寫,其他的最好還是寫上類型,增加代碼可讀性。

以上就是TypeScript的類型了,比較靈活也比較難,可能要在實(shí)際項(xiàng)目中用用就會(huì)比較好掌握。


向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI