类与接口
类与接口
interface(接口)
export declare function keys<T extends object>(): Array<keyof T>;
import { keys } from "ts-transformer-keys";
interface Props {
id: string;
name: string;
age: number;
}
const keysOfProps = keys<Props>();
console.log(keysOfProps); // ['id', 'name', 'age']
类
从
class Child extends Parent implements IChild, IOtherChild {
// 类属性
property: Type;
// 类属性默认值
defaultProperty: Type = "default value";
// 私有属性
private _privateProperty: Type;
// 静态属性
static staticProperty: Type;
// 构造函数
constructor(arg1: Type) {
super(arg1);
}
// 私有方法
private _privateMethod(): Type {}
methodProperty: (arg1: Type) => ReturnType;
overloadedMethod(arg1: Type): ReturnType;
overloadedMethod(arg1: OtherType): ReturnType;
overloadedMethod(arg1: CommonT): CommonReturnT {}
// 静态方法
static staticMethod(): ReturnType {}
subclassedMethod(arg1: Type): ReturnType {
super.subclassedMethod(arg1);
}
}
继承与实现
class TextStory implements Story {
title: string;
tags: string[];
static storyWithNoTags(title: string): TextStory {
return new TextStory(title, []);
}
constructor(title: string, ...tags) {
this.title = title;
this.tags = tags;
}
summary() {
return `TextStory ${this.title}`;
}
}
// 使用静态方法创建类对象
let story = TextStory.storyWithNoTags("Learning TypeScript");
class TutorialStory extends TextStory {
constructor(title: string, ...tags) {
// 调用父类构造函数
super(title, tags);
}
// 复写父类的方法
summary() {
return `TutorialStory: ${this.title}`;
}
}
现在
class Point {
x: number;
y: number;
}
interface Shape {
area(): number;
}
type Perimeter = {
perimiter(): number;
};
type RectangleShape = Shape & Perimeter & Point;
class Rectangle implements RectangleShape {}
// 等价于
class Rectangle implements Shape, Perimeter, Point {}
在实际项目中,我们往往会去定义公共父类,不过此时要注意父类的公共赋值和子类的默认值之间的冲突。
declare interface ObjectConstructor {
assign(target: any, ...sources: any[]): any;
}
class A {
a = 1;
constructor(data: {} = {}) {
Object.assign(this, data);
}
}
class B extends A {
a = 2;
// 父类调用 assign 在子类的属性域定义之前
constructor(data: {} = {}) {
super(data);
}
}
// B { a: 2 }
console.log(new B({ a: 3 }));
抽象类
abstract class StoryProcessorTemplate {
public process(url: string): Story {
const title: string = this.extractTitle(url);
const text: string = this.extractText(url);
const tags: string[] = this.extractTags(text);
return {
title: title,
tags: tags,
};
}
abstract extractTitle(url: string): string;
abstract extractText(url: string): string;
abstract extractTags(url: string): string[];
}
实例:项目管理

Entity
这是一个基类,它定义了其他类将继承的共同特征。
export class Entity {
private _id: number;
private _title: string;
private _creationDate: Date;
constructor(id: number, title: string) {
this._id = id;
this._title = title;
this._creationDate = new Date();
}
get id(): number {
return this._id;
}
get title(): string {
return this._title;
}
set title(title: string) {
this._title = title;
}
get creationDate(): Date {
return this._creationDate;
}
}
我们使用_id
,_title
和_creationDate
。使用下划线启动属性对于将它们与访问者(_id
_title
属性中设置的字符串。构造函数还会自动将_creationDate
定义为当前日期。我们在这个类定义中做的最后一件事是添加属性的
Task
import { Entity } from "./entity";
export class Task extends Entity {
private _completed: boolean;
private _priority: number;
get completed(): boolean {
return this._completed;
}
set completed(value: boolean) {
this._completed = value;
}
get priority(): number {
return this._priority;
}
set priority(value: number) {
this._priority = value;
}
}
由于此类将从_completed
和_priority
)及其访问器。请注意,我们没有在
Story
我们将创建的第三个类是
import { Entity } from "./entity";
import { Task } from "./task";
export class Story extends Entity {
private _completed: boolean;
private _responsible: string;
private _tasks: Array<Task> = [];
get completed(): boolean {
return this._completed;
}
set completed(value: boolean) {
this._completed = value;
}
get responsible(): string {
return this._responsible;
}
set responsible(value: string) {
this._responsible = value;
}
public addTask(task: Task) {
this._tasks.push(task);
}
get tasks(): Array<Task> {
return this._tasks;
}
public removeTask(task: Task): void {
let taskPosition = this._tasks.indexOf(task);
this._tasks.splice(taskPosition, 1);
}
}
就像
_completed
:标识故事是否已完成的标志。_responsible
:一个字符串,用于定义谁负责执行故事及其任务。_tasks
:一个包含零个或多个Task 实例的数组,由负责人执行。
对于前两个属性
Project
我们将创建的第四个也是最后一个类将是
import { Entity } from "./entity";
import { Story } from "./story";
export class Project extends Entity {
private _released: boolean;
private _stories: Array<Story>;
get released(): boolean {
return this._released;
}
set released(value: boolean) {
this._released = value;
}
public addStory(story: Story) {
this._stories.push(story);
}
get stories(): Array<Story> {
return this._stories;
}
public removeStory(story: Story) {
let storyPosition = this._stories.indexOf(story);
this._stories.splice(storyPosition, 1);
}
}
我们通过导入_released
和_stories
。
Completable
假设我们想要在任务或故事被标记为已完成时触发电子邮件。我们可以定义一个表示可完成项的接口,而不是创建两个不同的函数来单独处理每个类型。为了练习,让我们使用以下源代码在
export interface Completable {
title: string;
completed: boolean;
completedAt?: Date;
}
定义此接口后,我们可以使用它来限制哪些对象可以传递给发送电子邮件的函数。让我们在
import { Task } from "./task";
import { Completable } from "./completable";
function sendCompletionEmail(completable: Completable) {
if (!completable.completed) {
// ignore incompleted entities
console.error(
`Please, complete '${completable.title}' before sending email.`
);
return;
}
console.log(`Sending email about '${completable.title}'`);
// ...
}
let bugFix = new Task(1, "Weirdo flying bug");
sendCompletionEmail(bugFix);
bugFix.completed = true;
sendCompletionEmail(bugFix);
请注意,
// 修改 Task 与 Story 的接口继承
export class Task extends Entity implements Completable {
// ... nothing else changes here
}
export class Story extends Entity implements Completable {
// ... nothing else changes here
}