接口
TypeScript的核心原则之一是对值所具有的结构进行类型检查。
interface LabelledValue {
label: string;
}
function printLabel(labelledObj: LabelledValue) {
console.log(labelledObj.label);
}
let myObj = {size: 10, label: "Size 10 Object"};
printLabel(myObj);
可选属性
interface SquareConfig {
width: number
height: number
color?: string // 可选属性
}
只读属性
只能在刚创建时修改其值
interface Point {
readonly x: number;
readonly y: number;
}
额外的属性检查
如果 SquareConfig带有上面定义的类型的color和width属性,并且还会带有任意数量的其它属性,可以这样定义:
interface SquareConfig {
width: number
color?: string
[propName: string]: any
}
函数类型
interface SearchFunc {
(source: string, subString: string): boolean
}
// 对于函数类型的类型检查来说,函数的参数名不需要与接口里定义的名字相匹配。
let mySearch: SearchFunc;
mySearch = function(src: string, sub: string): boolean {
let result = src.search(sub);
return result > -1;
}
可索引的类型
interface StringArray {
[index: number]: string;
}
let myArray: StringArray;
myArray = ["Bob", "Fred"];
let myStr: string = myArray[0];
类类型
interface ClockInterface {
currentTime: Date;
setTime(d: Date);
}
// 通过 implements 描述
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
混合类型
一个对象可以同时做为函数和对象使用,并带有额外的属性
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;
类
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();
继承
通过 extends 关键字
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);
}
}
公共,私有与受保护的修饰符
public(默认)
在TypeScript里,成员都默认为 public。
class Animal {
public name: string;
}
private
当成员被标记成private时,它就不能在声明它的类的外部访问。
class Animal {
private name: string
constructor(theName: string) { this.name = theName; }
}
new Animal('Cat').name // 错误: 'name' 是私有的.
protected
protected与private修饰符的行为很相似,但有一点不同, protected成员在派生类中仍然可以访问。
class Person {
protected name: string
constructor(name: string) { this.name = name }
}
class Employee extends Person {
private department: string
public getElevatorPitch() {
return `my name is ${this.name} and I work in ${this.department}.`
}
}
let dick = new Employee("Howard", "Sales")
console.log(dick.getElevatorPitch());
console.log(dick.name); // 错误
readonly修饰符
readonly关键字将属性设置为只读的。 只读属性必须在声明时或构造函数里被初始化。
class Octopus {
readonly name: string;
constructor (theName: string) {
this.name = theName;
}
}
let dad = new Octopus("Man with the 8 strong legs");
dad.name = "Man with the 3-piece suit"; // 错误! name 是只读的.
存取器
TypeScript支持通过getters/setters来截取对对象成员的访问。
let passcode = "secret passcode";
class Employee {
private _fullName: string;
get fullName(): string {
return this._fullName;
}
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);
}
抽象类
抽象类做为其它派生类的基类使用。 它们一般不会直接被实例化。
abstract class Department { ... }
class AccountingDepartment extends Department { ... }
let department: Department // 允许创建一个对抽象类型的引用
department = new Department() // 错误: 不能创建一个抽象类的实例
department = new AccountingDepartment() // 允许对一个抽象子类进行实例化和赋值