接口
定义方式
直联定义
function printLabel(labelledObj: { label: string }) {
console.log(labelledObj.label);
}
引用定义
interface LabelledValue {
label: string;
}
function printLabel(labelledObj: LabelledValue) {
console.log(labelledObj.label);
}
ts会检查参数是否含有接口中指定的项,其他多余项和项的顺序不参与判断
基础语法
可选属性
可选属性的好处之一是可以对可能存在的属性进行预定义,好处之二是可以捕获引用了不存在的属性时的错误。
interface SquareConfig {
color?: string;
width?: number;
}
只读属性
只能在对象刚刚创建的时候修改其值。 你可以在属性名前用 readonly
来指定只读属性
interface Point {
readonly x: number;
readonly y: number;
}
相似:let ro: ReadonlyArray = a;
该数组无法被更改了
额外的属性检查
error: ‘colour’ not expected in type ‘SquareConfig’
断言
let mySquare = createSquare({ width: 100, opacity: 0.5 } as SquareConfig);
上文适合,当函数createSquare的参数类型为SquareConfig接口的指定,但是包含SquareConfig接口未指出的属性时
给出兼容项
interface SquareConfig {
color?: string;
width?: number;
[propName: string]: any;
}
在这我们要表示的是SquareConfig
可以有任意数量的属性,并且只要它们不是color
和width
,那么就无所谓它们的类型是什么
接口类型
函数类型
函数类型实质上是指定函数的参数和返回值类型
interface SearchFunc {
(source: string, subString: string): boolean;
}
let mySearch: SearchFunc;
mySearch = function(source: string, subString: string): boolean {
let result = source.search(subString);
return result > -1;
}
索引类型
定义索引接口
interface StringArray {
[index: number]: string;
}
let myArray: StringArray;
myArray = ["Bob", "Fred"];
let myStr: string = myArray[0];
只读索引
interface ReadonlyStringArray {
readonly [index: number]: string;
}
let myArray: ReadonlyStringArray = ["Alice", "Bob"];
myArray[2] = "Mallory"; // error!
类类型
接口制定类的部分属性与方法参数
interface ClockInterface {
currentTime: Date;
setTime(d: Date);
}
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 Greeter {
greeting: string; //声明属性 this调用类属性
constructor(message: string) { // 构造函数
this.greeting = message;
}
greet() { // 声明方法
return "Hello, " + this.greeting;
}
}
// 创建一个 Greeter类型的新对象,并执行构造函数初始化它。
let greeter = new Greeter("world");
继承
属性方法继承
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
关键字。 派生类通常被称作 子类,基类通常被称作 超类。
super调用基类/超类
在子类的构造函数中,调用超类的构造函数。
constructor(name: string) { super(name); }
调用超类的方法 可用在子类的方法重写中
super.move(distanceInMeters);
在构造函数里访问
this
的属性之前,我们 一定要调用super()
属性修饰词
public
在TypeScript里,成员都默认为 public
。
public name: string;
private
不能在声明它的类的外部访问。
class Animal {
private name: string;
constructor(theName: string) { this.name = theName; }
}
new Animal("Cat").name; // 错误: 'name' 是私有的.
protected
派生类后,可以在派生类内部访问,实例化后可以通过方法访问,但是不能通过实例化后的对象直接访问
构造函数也可以被标记成 protected
。 这意味着这个类不能在包含它的类外被实例化,但是能被继承。
readonly
可以使用 readonly
关键字将属性设置为只读的。 只读属性必须在声明时或构造函数里被初始化。
参数属性
constructor(readonly name: string) {
}
仅在构造函数里使用 readonly name: string
参数来创建和初始化 name
成员。 我们把声明和赋值合并至一处。
参数属性通过给构造函数参数前面添加一个访问限定符来声明。 使用 private
限定一个参数属性会声明并初始化一个私有成员;对于 public
和 protected
来说也是一样。
存取器
set
set fullName(newName: string) {
if (passcode && passcode == "secret passcode") {
this._fullName = newName;
}
else {
console.log("Error: Unauthorized update of employee!");
}
}
get
get fullName(): string {
return this._fullName;
}
静态属性
这些属性存在于类本身上面而不是类的实例上。
每个实例想要访问这个属性的时候,都要在 origin
前面加上类名。 如同在实例属性上使用 this.
前缀来访问属性一样,这里我们使用 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;
}
抽象类
abstract
关键字是用于定义抽象类和在抽象类内部定义抽象方法。
不能创建一个抽象类的实例,抽象类中的抽象方法不包含具体实现并且必须在派生类中实现。
abstract class Department {
constructor(public name: string) {
}
printName(): void {
console.log('Department name: ' + this.name);
}
abstract printMeeting(): void; // 必须在派生类中实现
}
class AccountingDepartment extends Department {
constructor() {
super('Accounting and Auditing'); // 在派生类的构造函数中必须调用 super()
}
printMeeting(): void {
console.log('The Accounting Department meets each Monday at 10am.');
}
generateReports(): void {
console.log('Generating accounting reports...');
}
}
let department: Department; // 允许创建一个对抽象类型的引用
department = new Department(); // 错误: 不能创建一个抽象类的实例
department = new AccountingDepartment(); // 允许对一个抽象子类进行实例化和赋值
department.printName();
department.printMeeting();
department.generateReports(); // 错误: 方法在声明的抽象类中不存在