基礎(chǔ)類型
TypeScript支持與JavaScript幾乎相同的數(shù)據(jù)類型,包括最簡單的數(shù)據(jù)單元:數(shù)字,字符串逞频,結(jié)構(gòu)體,布爾值等基协,定義方式如下:
// 布爾值
let isDone: boolean = false;
// 數(shù)字澜驮,支持十進(jìn)制、十六進(jìn)制卦绣、二進(jìn)制和八進(jìn)制
let decLiteral: number = 6;
let hexLiteral: number = 0xf00d;
let binaryLiteral: number = 0b1010;
let octalLiteral: number = 0o744;
// 字符串
let name: string = "bob";
// 數(shù)組
let list: number[] = [1, 2, 3]; // 可以在元素類型后面接上 [],表示由此類型元素組成的一個數(shù)組
let list: Array<number> = [1, 2, 3]; // 或者使用數(shù)組泛型
// 元組
// 元組類型允許表示一個已知元素數(shù)量和類型的數(shù)組,各元素的類型不必相同樟凄。
let x: [string, number];
// 枚舉
// enum類型是對JavaScript標(biāo)準(zhǔn)數(shù)據(jù)類型的一個補充。 像C#等其它語言一樣叔壤,使用枚舉類型可以為一組數(shù)值賦予友好的名字。
// 默認(rèn)情況下妄田,從0開始為元素編號。 你也可以手動的指定成員的數(shù)值。
enum Color {Red, Green, Blue}
let c: Color = Color.Green;
除了這些最簡單的數(shù)據(jù)單元外珊泳,TypeScript的基礎(chǔ)類型還包括Any、Void、Object等:
- Any: 有時候,我們會想要為那些在編程階段還不清楚類型的變量指定一個類型愉镰。 這些值可能來自于動態(tài)的內(nèi)容,比如來自用戶輸入或第三方代碼庫碗降。 這種情況下动看,我們不希望類型檢查器對這些值進(jìn)行檢查而是直接讓它們通過編譯階段的檢查。 那么我們可以使用 any類型來標(biāo)記這些變量:
let notSure: any = 4;
notSure = "maybe a string instead";
notSure = false; // okay, definitely a boolean
- Void: 某種程度上來說,void類型像是與any類型相反奶甘,它表示沒有任何類型吭产。 當(dāng)一個函數(shù)沒有返回值時臣淤,你通常會見到其返回值類型是 void:
function warnUser(): void {
console.log("This is my warning message");
}
- Null 和 Undefined: TypeScript里邑蒋,undefined和null兩者各自有自己的類型分別叫做undefined和null。 和 void相似逮京,它們的本身的類型用處不是很大:
let u: undefined = undefined;
let n: null = null;
- Never: never類型表示的是那些永不存在的值的類型。 例如策严, never類型是那些總是會拋出異常或根本就不會有返回值的函數(shù)表達(dá)式或箭頭函數(shù)表達(dá)式的返回值類型倔韭; 變量也可能是 never類型,當(dāng)它們被永不為真的類型保護(hù)所約束時份名。
never類型是任何類型的子類型,也可以賦值給任何類型辰如;然而凯正,沒有類型是never的子類型或可以賦值給never類型(除了never本身之外)。 即使 any也不可以賦值給never梧疲。
// 返回never的函數(shù)必須存在無法達(dá)到的終點
function error(message: string): never {
throw new Error(message);
}
// 推斷的返回值類型為never
function fail() {
return error("Something failed");
}
// 返回never的函數(shù)必須存在無法達(dá)到的終點
function infiniteLoop(): never {
while (true) {
}
}
- Object: object表示非原始類型,也就是除number米者,string,boolean败明,symbol妻顶,null或undefined之外的類型讳嘱。
使用object類型,就可以更好的表示像Object.create這樣的API嬉挡。例如:
declare function create(o: object | null): void;
create({ prop: 0 }); // OK
create(null); // OK
create(42); // Error
- 類型斷言: 類型斷言好比其它語言里的類型轉(zhuǎn)換,但是不進(jìn)行特殊的數(shù)據(jù)檢查和解構(gòu)基括。 它沒有運行時的影響匠璧,只是在編譯階段起作用。 TypeScript會假設(shè)你裁厅,程序員,已經(jīng)進(jìn)行了必須的檢查。
// 尖括號寫法
let someValue: any = "this is a string";
let strLength: number = (<string>someValue).length;
// as寫法茬故,jsx中只能用這個
let someValue: any = "this is a string";
let strLength: number = (someValue as string).length;
接口
在TypeScript中,接口存在的意義就是對值的類型進(jìn)行命名和為你的代碼或第三方代碼定義契約钾腺。
基礎(chǔ)用法
interface LabelledValue {
label: string;
}
function printLabel(labelledObj: LabelledValue) {
console.log(labelledObj.label);
}
let myObj = {size: 10, label: "Size 10 Object"};
printLabel(myObj);
和其它語言不同的是,只要傳入的對象滿足接口定義的必要條件,那么就是被允許的厢破。
可選屬性
interface SquareConfig {
color?: string;
width?: number;
}
function createSquare(config: SquareConfig): {color: string; area: number} {
let newSquare = {color: "white", area: 100};
if (config.color) {
newSquare.color = config.color;
}
if (config.width) {
newSquare.area = config.width * config.width;
}
return newSquare;
}
let mySquare = createSquare({color: "black"});
若要定義可選屬性,可在可選屬性名字定義的后面加一個?符號加勤。
可選屬性可以對可能存在的屬性進(jìn)行預(yù)定義未檩,并且可以捕獲引用了不存在的屬性時的錯誤冤狡。
只讀屬性
interface Point {
readonly x: number;
readonly y: number;
}
let p1: Point = { x: 10, y: 20 };
p1.x = 5; // error!
在屬性名前用readonly來指定只讀屬性悲雳。
let a: number[] = [1, 2, 3, 4];
let ro: ReadonlyArray<number> = a;
ro[0] = 12; // error!
ro.push(5); // error!
ro.length = 100; // error!
a = ro; // error!
TypeScript具有ReadonlyArray<T>類型,它與Array<T>相似晴楔,只是把所有可變方法都去掉了。
額外的屬性檢查
interface SquareConfig {
color?: string;
width?: number;
}
function createSquare(config: SquareConfig): { color: string; area: number } {
// ...
}
// error: 'colour' not expected in type 'SquareConfig'
let mySquare = createSquare({ colour: "red", width: 100 });
上面的代碼會報錯,原因是TypeScript會認(rèn)為這段代碼可能存在bug导匣。對象字面量會被特殊對待而且會經(jīng)過額外屬性檢查,當(dāng)將它們賦值給變量或作為參數(shù)傳遞的時候缓待。如果一個對象字面量存在任何“目標(biāo)類型”不包含的屬性時旋炒,就會報錯瘫镇。
繞開這些檢查的方式有以下幾種:
// 使用類型斷言
let mySquare = createSquare({ width: 100, opacity: 0.5 } as SquareConfig);
// 更改接口的定義谚咬,使得它可以接受任意其它的屬性
interface SquareConfig {
color?: string;
width?: number;
[propName: string]: any;
}
// 將對象賦值給一個變量
let squareOptions = { colour: "red", width: 100 };
let mySquare = createSquare(squareOptions);
函數(shù)類型
interface SearchFunc {
(source: string, subString: string): boolean;
}
let mySearch: SearchFunc;
mySearch = function(source: string, subString: string) {
let result = source.search(subString);
return result > -1;
}
接口也可以描述函數(shù)類型,如上面代碼所示,它就像是一個只有參數(shù)列表和返回值類型的函數(shù)定義尚辑。參數(shù)列表里的每個參數(shù)都需要名字和類型。
可索引的類型
interface StringArray {
[index: number]: string;
}
let myArray: StringArray;
myArray = ["Bob", "Fred"];
let myStr: string = myArray[0];
TypeScript支持兩種索引簽名:字符串和數(shù)字澈蝙。 可以同時使用兩種類型的索引盐杂,但是數(shù)字索引的返回值必須是字符串索引返回值類型的子類型链烈。
類類型
interface ClockInterface {
currentTime: Date;
setTime(d: Date);
}
class Clock implements ClockInterface {
currentTime: Date;
setTime(d: Date) {
this.currentTime = d;
}
constructor(h: number, m: number) { }
}
TypeScript中接口同樣可以用來明確的強制一個類去符合某種契約擦秽。
繼承接口
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;
TypeScript中的接口可以相互繼承,并且一個接口可以繼承多個接口
混合類型
一個對象可以同時做為函數(shù)和對象使用触幼,并帶有額外的屬性堂鲤。
interface Counter {
(start: number): string;
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;
在使用JavaScript第三方庫的時候,可能需要像上面那樣去完整地定義類型。