Как мне написать интерфейс для класса с прототипными методами в TS?

#typescript #class #methods #prototype #factory

#typescript #класс #методы #прототип #фабрика

Вопрос:

Я немного поработал над этой проблемой и решил, что в конце концов пойму или найду достойное объяснение. Я прочитал много статей в руководстве по TS, поискал в Google () и искал 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 из class amp; 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;

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

}

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

Мне кажется странным, что я не могу найти больше тем об этом сценарии, как будто это что-то очевидное или прямо объясненное в руководстве, но, похоже, я не могу его найти. Вы просто не должны добавлять вещи непосредственно в прототип в TS? Я даже пытался использовать Object.setPrototypeOf() в конструкторе, чтобы посмотреть, примет ли он его, но безуспешно.

Что я делаю не так? Должен ли я использовать ТОЛЬКО классы в TS и помещать методы непосредственно в класс? Если это так, то как фабричные функции вписываются в TS? Может кто-нибудь показать мне различные методы обхода этих ситуаций?

Игровая площадка TS

Ответ №1:

Вы просто не должны добавлять вещи непосредственно в прототип в 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();
 

Или, если вам не нужно сохранять конструктор закрытым, вы можете просто использовать factory в качестве вспомогательной функции вне класса:

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

class Example() {}