let input = [1, 2]; let [first, second] = input; console.log(first); // outputs 1 console.log(second); // outputs 2
上面的寫法等價於:typescript
first = input[0]; second = input[1];
利用解構賦值交換變量:數組
[first, second] = [second, first];
函數參數解構:函數
function f ([first, second]: [number, number]) [ console.log(first) console.log(second) ] f(1, 2)
解構剩餘參數:this
let [first, ...rest] = [1, 2, 3, 4] console.log(first) // 1 console.log(rest) // [2, 3, 4]
也能夠忽略其它參數:rest
let [first] = [1, 2, 3, 4]; console.log(first); // outputs 1
或者跳過解構:code
let [, second, , fourth] = [1, 2, 3, 4]
示例一:對象
let o = { a: "foo", b: 12, c: "bar" }; let { a, b } = o;
就像數組解構,你能夠用沒有聲明的賦值:繼承
let a: number, b: number; ({a, b} = {a: 123, b: 456}) console.log(a, b) // 123 456
你能夠在對象裏使用 ...
語法建立剩餘變量:ip
let { a, ...passthrough } = o; let total = passthrough.b + passthrough.c.length;
你也能夠給屬性以不一樣的名字:get
let { a: newName1, b: newName2 } = o;
注意,這裏的冒號不是指示類型的。 若是你想指定它的類型, 仍然須要在其後寫上完整的模式。
let {a, b}: {a: string, b: number} = o;
function keepWholeObject(wholeObject: { a: string, b?: number }) { let { a, b = 1001 } = wholeObject; }
type C = {a: string, b?: number} function f ({a, b}: C): void { // ... }
class Person { name: string; age: number; constructor(name: string, age: number) { this.name = name; this.age = age; } sayHello() { console.log(this.name); } } let zs: Person = new Person('張三', 18);
class Animal { move(distanceInMeters: number = 0) { console.log(`Animal moved ${distanceInMeters}m.`); } } class Dog extends Animal { bark() { console.log('Woof! Woof!'); } } const dog = new Dog(); dog.bark(); dog.move(10); dog.bark();
這個例子展現了最基本的繼承:類從基類中繼承了屬性和方法。 這裏, Dog
是一個 派生類,它派生自 Animal
基類,經過 extends
關鍵字。 派生類一般被稱做 子類,基類一般被稱做 超類。
由於 Dog
繼承了 Animal
的功能,所以咱們能夠建立一個 Dog
的實例,它可以 bark()
和 move()
。
下面是一個更復雜的例子:
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: Animal = new Horse("Tommy the Palomino"); sam.move(); tom.move(34);
與前一個例子的不一樣點是,派生類包含了一個構造函數,它 必須調用 super()
,它會執行基類的構造函數。 並且,在構造函數裏訪問 this
的屬性以前,咱們 必定要調用 super()
。 這個是TypeScript強制執行的一條重要規則。
這個例子演示瞭如何在子類裏能夠重寫父類的方法。 Snake
類和 Horse
類都建立了 move
方法,它們重寫了從Animal
繼承來的 move
方法,使得 move
方法根據不一樣的類而具備不一樣的功能。 注意,即便 tom
被聲明爲Animal
類型,但由於它的值是 Horse
,調用 tom.move(34)
時,它會調用 Horse
裏重寫的方法:
Slithering... Sammy the Python moved 5m. Galloping... Tommy the Palomino moved 34m.
public
開放的public
class Animal { public name: string; public constructor(theName: string) { this.name = theName; } public move(distanceInMeters: number) { console.log(`${this.name} moved ${distanceInMeters}m.`); } }
private
私有的class Person { public name: string; public age: number = 18; private type: string = 'human' public constructor (name, age) { this.name = name this.age = age } }
protected
受保護的private
相似,可是能夠被繼承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()); console.log(howard.name); // 錯誤
注意,咱們不能在 Person
類外使用 name
,可是咱們仍然能夠經過 Employee
類的實例方法訪問,由於Employee
是由 Person
派生而來的。
readonly
只讀的在上面的例子中,咱們不得不定義一個受保護的成員 name
和一個構造函數參數 theName
在 Person
類裏,而且馬上給 name
和 theName
賦值。 這種狀況常常會遇到。 參數屬性能夠方便地讓咱們在一個地方定義並初始化一個成員。
class Person { name: string; age: number; constructor(name: string, age: number) { this.name = name; this.age = age; } }
能夠簡寫爲:
class Person { constructor(public name: string, public age: number) { } }
let passcode = "secret passcode"; class Employee { // 私有成員,外部沒法訪問 private _fullName: string; // 當訪問 實例.fullName 的時候會調用 get 方法 get fullName(): string { return this._fullName; } // 當對 實例.fullName = xxx 賦值的時候會調用 set 方法 set fullName(newName: string) { if (passcode && passcode == "secret passcode") { this._fullName = newName; } else { console.log("Error: Unauthorized update of employee!"); } } } let employee = new Employee(); employee.fullName = "Bob Smith"; if (employee.fullName) { alert(employee.fullName); }
static
關鍵字class Grid { static origin = {x: 0, y: 0}; calculateDistanceFromOrigin(point: {x: number; y: number;}) { let xDist = (point.x - Grid.origin.x); let yDist = (point.y - Grid.origin.y); return Math.sqrt(xDist * xDist + yDist * yDist) / this.scale; } constructor (public scale: number) { } } let grid1 = new Grid(1.0); // 1x scale let grid2 = new Grid(5.0); // 5x scale console.log(grid1.calculateDistanceFromOrigin({x: 10, y: 10})); console.log(grid2.calculateDistanceFromOrigin({x: 10, y: 10}));