TypeScript(JavaScript的超集)
始於JavaScript,歸於JavaScript
TypeScript從今天數以百萬計的JavaScript開發者所熟悉的語法和語義開始。使用現有的JavaScript代碼,包括流行的JavaScript庫,並從JavaScript代碼中調用TypeScript代碼。
TypeScript可以編譯出純淨、 簡潔的JavaScript代碼,並且可以運行在任何瀏覽器上、Node.js環境中和任何支持ECMAScript 3(或更高版本)的JavaScript引擎中
基礎類型
TypeScript支持與JavaScript幾乎相同的數據類型,
布爾值
let isDone: boolean = false;
數字
let decLiteral: number = 6;
let hexLiteral: number = 0xf00d;
let binaryLiteral: number = 0b1010;
let octalLiteral: number = 0o744;
字符串
let name: string = "bob";
//模版字符串
let name: string = `Gene`;
let age: number = 37;
let sentence: string = `Hello, my name is ${ name }.
數組
//1
let list: number[] = [1, 2, 3];
//2
let list: Array<number> = [1, 2, 3];
元組 Tuple
元組類型允許表示一個已知元素數量和類型的數組,各元素的類型不必相同。 比如,你可以定義一對值分別爲 string和number類型的元組。
// Declare a tuple type
let x: [string, number];
// Initialize it
x = ['hello', 10]; // OK
// Initialize it incorrectly
x = [10, 'hello']; // Error
當訪問一個越界的元素,會使用聯合類型替代
x = [10, ‘hello’,29]; //
枚舉
像JAVA ,C#等其它語言一樣,使用枚舉類型可以爲一組數值賦予友好的名字
enum Color {Red, Green, Blue};
let c: Color = Color.Green; //1
enum Color {Red = 1, Green, Blue};
let colorName: string = Color[2];
alert(colorName);
任意值
有時候,我們會想要爲那些在編程階段還不清楚類型的變量指定一個類型。 這些值可能來自於動態的內容, 這種情況下,我們不希望類型檢查器對這些值進行檢查而是直接讓它們通過編譯階段的檢查。 那麼我們可以使用 any類型來標記這些變量:
let notSure: any = 4;
notSure = "maybe a string instead";
notSure = false; // okay, definitely a boolean
空值
當一個函數沒有返回值時,你通常會見到其返回值類型是 void:
function warnUser(): void {
alert("This is my warning message");
}
//void類型的變量 只能爲它賦予undefined和null:
let unusable: void = undefined;
函數
function buildName(firstName: string, lastName: string):string {
return firstName + " " + lastName;
}
let result1 = buildName("Bob"); // error, too few parameters
let result2 = buildName("Bob", "Adams", "Sr."); // error, too many parameters
let result3 = buildName("Bob", "Adams"); // ah, just right
Null 和 Undefined
let u: undefined = undefined;
let n: null = null;
let t: number = null;
類型斷言
類型斷言有兩種形式。 其一是“尖括號”語法:
let someValue: any = "this is a string";
let strLength: number = (<string>someValue).length;
另一個爲as語法
let someValue: any = "this is a string";
let strLength: number = (someValue as string).length;
接口
接口的作用就是爲這些類型命名和爲你的代碼定義契約。
function printLabel(labelledObj: { label: string }) {
console.log(labelledObj.label);
}
let myObj = { size: 10, label: "Size 10 Object" };
printLabel(myObj);
//接口重寫後
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"});
函數類型
除了描述帶有屬性的普通對象外,接口也可以描述函數類型。爲了使用接口表示函數類型,我們需要給接口定義一個調用簽名。它就像是一個只有參數列表和返回值類型的函數定義。參數列表裏的每個參數都需要名字和類型。
interface SearchFunc {
(source: string, subString: string): boolean;
}
let mySearch: SearchFunc;
//函數的參數名不需要與接口裏定義的名字相匹配
mySearch = function(source1: string, subString1: string) {
let result = source.search(subString);
if (result == -1) {
return false;
}
else {
return true;
}
}
實現接口
與C#或Java裏接口的基本作用一樣,TypeScript也能夠用它來明確的強制一個類去符合某種契約。
interface ClockInterface {
currentTime: Date;
setTime(d: Date); //return void
}
class Clock implements ClockInterface {
currentTime: Date;
setTime(d: Date) {
this.currentTime = d;
}
constructor(h: number, m: number) { }
}
接口繼承
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;
類
繼承
class Animal {
name:string;
constructor(theName: string) { this.name = theName; }
move(distanceInMeters: number = 0) {
console.log(`${this.name} moved ${distanceInMeters}m.`);
}
}
class Snake extends Animal {
constructor(name: string) { super(name); }
move(distanceInMeters = 5) {
console.log("Slithering...");
super.move(distanceInMeters);
}
}
class Horse extends Animal {
constructor(name: string) { super(name); }
move(distanceInMeters = 45) {
console.log("Galloping...");
super.move(distanceInMeters);
}
}
let sam = new Snake("Sammy the Python");
let tom = new Horse("Tommy the Palomino");
sam.move();
tom.move(34);
//Slithering...
//Sammy the Python moved 5m.
//Galloping...
//Tommy the Palomino moved 34m.
公共,私有與受保護的修飾符
默認爲public
理解private
當成員被標記成private時,它就不能在聲明它的類的外部訪問
class Animal {
private name: string;
constructor(theName: string) { this.name = theName; }
}
new Animal("Cat").name; // Error: 'name' is private;
理解protected
protected修飾符與private修飾符的行爲很相似,但有一點不同,protected成員在派生類中仍然可以訪問
class Person {
protected name: string;
constructor(name: string) { this.name = name; }
}
class Employee extends Person {
private department: string;
constructor(name: string, department: string) {
super(name)
this.department = department;
}
public getElevatorPitch() {
return `Hello, my name is ${this.name} and I work in ${this.department}.`;
}
}
let howard = new Employee("Howard", "Sales");
console.log(howard.getElevatorPitch());
readonly修飾符
你可以使用readonly關鍵字將屬性設置爲只讀的。 只讀屬性必須在聲明時或構造函數裏被初始化。
class Octopus {
readonly name: string;
readonly numberOfLegs: number = 8;
constructor (theName: string) {
this.name = theName;
}
}
let dad = new Octopus("Man with the 8 strong legs");
dad.name = "Man with the 3-piece suit"; // error! name is readonly.