您好,登錄后才能下訂單哦!
上一篇講了基礎(chǔ)類型,基本上用基礎(chǔ)類型足夠開發(fā)了,不過如果要更高效的開發(fā),還是要看下高級(jí)類型,這篇和C#共同點(diǎn)并不多,只是延用這個(gè)主題。
可以從字面上進(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());
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;
聯(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ù)p
是string
類型,從而在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
綜合上面的字符串字面量類型、聯(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ì)比較好掌握。
免責(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)容。