首页 > 解决方案 > 如何在 TS 中为具有原型方法的类编写接口?

问题描述

我一直在解决这个问题一段时间,并认为我最终会理解或遇到一个体面的解释。我已经阅读了 TS 手册中的许多文章,google()'d 了它,并搜索了 SO,但还没有找到答案。

我需要知道如何正确、完整地在 TS 类/接口中键入原型方法。

interface UploadFileInterface {
    contentSizes: number[];
    chunks: [];
    chunksDone: number;
    getChunkLength: (id: number) => void;
    name: string;
    size: string;
    chunksQuantity: number;

}

class UploadedFile implements UploadFileInterface {

    contentSizes: Array<number> = [];
    chunks: [] = [];
    chunksDone: number = 0;
    getChunkLength: (id: number) => void;
     ^^^^^^^^ - 'Property 'getChunkLength' has no initializer and is not definitely assigned in the constructor.'

    constructor(
        public name: string, 
        public size: string, 
        public chunksQuantity: number
        ) {}

}

UploadedFile.prototype.getChunkLength = function(id: number): void {
    
}

我得到这个可怕的'属性'getChunkLength'没有初始化器,并且没有在构造函数中明确分配。错误。

我试图将 getChunkLength 完全从类和接口中移开,并将其保留在原型上的编写方式(因为接口应该只描述类的“实例端”),但随后错误转移到了函数在原型上:

interface UploadFileInterface {
    contentSizes: number[];
    chunks: [];
    chunksDone: number;
    //getChunkLength: (id: number) => void;
    name: string;
    size: string;
    chunksQuantity: number;

}

class UploadedFile implements UploadFileInterface {

    contentSizes: Array<number> = [];
    chunks: [] = [];
    chunksDone: number = 0;
    //getChunkLength: (id: number) => void;

    constructor(
        public name: string, 
        public size: string, 
        public chunksQuantity: number
        ) {}

}

UploadedFile.prototype.getChunkLength = function(id: number): void {
    
}

我觉得很奇怪,我似乎找不到更多关于这种情况的线索,就像它在手册中很明显或直接解释的那样,但我似乎找不到。您是否不应该直接将东西添加到 TS 中的原型中?我什至尝试在构造函数中使用 Object.setPrototypeOf() 来查看它是否会接受它,但没有运气。

我究竟做错了什么?我应该只在 TS 中使用类并将方法直接放在类上吗?如果是这样,工厂函数如何适应 TS?有人可以告诉我解决这些情况的不同技巧吗?

TS游乐场

标签: typescriptclassmethodsprototypefactory

解决方案


您是否不应该直接将东西添加到 TS 中的原型中?

Typescript 期望你使用类语法来定义你的类。这种语法可能没有明确提到原型,但功能仍然被添加到原型中。

所以下面的例子会在原型中添加一个 getChunkLength 函数:

class UploadedFile implements UploadFileInterface {
    contentSizes: Array<number> = [];
    chunks: [] = [];
    chunksDone: number = 0;

    constructor(
        public name: string, 
        public size: string, 
        public chunksQuantity: number
    ) {}

    getChunkLength(id: string): void {
    
    }
}

如果您遇到需要显式修改原型的特殊情况,那么 typescript 将无法告诉您您在做什么,您需要断言该属性确实已定义。这是通过以下方式完成的!

class UploadedFile implements UploadFileInterface {

    contentSizes: Array<number> = [];
    chunks: [] = [];
    chunksDone: number = 0;
    getChunkLength!: (id: number) => void;

    // ... constructor omitted
}

UploadedFile.prototype.getChunkLength = function(id: number): void {
    
}

工厂函数如何适应 TS?

您可以使用类上的静态函数来执行此操作:

class Example () {
  public static createInstance() {
    return new Example();
  }

  private constructor() {}
}

// used like:
const example1 = Example.createInstance();

或者,如果您不需要将构造函数保持为私有,则可以让工厂成为类外部的辅助函数:

const createInstance = () => new Example();

class Example() {}

推荐阅读