CMS

【Typescript】接口、类

接口

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() // 允许对一个抽象子类进行实例化和赋值

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注