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}));