如何在 TS 中使用原型方法为 class 编写接口?

How do I write an interface for a class with prototype methods in TS?

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

我需要知道如何在 TS class/interface.

中正确、完整地键入 原型 方法
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 完全从 class & 接口中移除,并保留它在原型上的写法(因为接口应该只描述 'instance side' 的 class), 但随后错误转移到原型上的函数:

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 中使用 classes 并将方法直接放在 class 上吗?如果是这样,工厂函数如何适应 TS?有人可以告诉我解决这些情况的不同技巧吗?

TS Playground

Are you just not supposed to add things directly to the prototype in TS?

Typescript 希望您使用 class 语法来定义您的 classes。这个语法可能没有明确提到原型,但是函数被添加到原型中none越少。

所以下面的例子会在原型中添加一个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 {
    
    }
}

如果您遇到需要显式修改原型的异常情况,那么打字稿将无法告诉您您在做什么,您需要断言 属性 确实被定义为。这是通过 !:

class UploadedFile implements UploadFileInterface {

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

    // ... constructor omitted
}

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

how do factory functions fit into TS?

您可以使用 class 上的静态函数来实现:

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

  private constructor() {}
}

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

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

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

class Example() {}