Переопределение объектного интерфейса в TypeScript - PullRequest
0 голосов
/ 10 июля 2020

Можно ли повторно объявить объект с другим интерфейсом, чтобы обеспечить перегрузку существующих методов?

В моем конкретном примере c используется EventEmitter (конкретно я использую eventemitter3 пакет, но он соответствует всем спецификациям NodeJS.EventEmitter).

Итак, у меня есть этот файл, объявляющий экземпляр singleton:

import { EventEmitter } from 'eventemitter3';

export const instance = new EventEmitter();

// I could do this:
instance.on('event-foo', 'foo-data');
// or this too
instance.on('event-bar', 12345);

Я хочу ограничить методы, чтобы обеспечить лучший набор текста, поэтому я может указывать только правильные события, потому что нет ограничений на то, какие параметры я могу передавать с типами по умолчанию.

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

const originalInstance = new EventEmitter();

function on('event-foo', data: string): void;
function on('event-bar', data: number): void;
function on(event: string, data: string | number): void {
  originalInstance.on(event, data);
}

// having this you can provide a wrapper like the following:
export const instance = {
  on,
// ...
};

Но создание оболочки создает дополнительный код, который я считаю ненужным ... поэтому мой вопрос: есть ли способ «мягко» перепечатать исходный объект без лишнего кода? Только с использованием типов. Примерно так:

const originalInstance = new EventEmitter();

interface NewDefinitions {
  //...
}

export const instance = originalInstance as NewDefinitions;

Проблема, которую я обнаружил, заключается в том, что вы не можете предоставить определения перегрузки внутри интерфейсов, только при создании функции afaik ...

Other hack Я обнаружил, что использует declare вот так:

declare function on('event-foo', data: string): void;
declare function on('event-bar', data: number): void;

interface NewDefinitions {
  on: typeof on;
  // ...
}

export const instance = (originalInstance as unknown) as NewDefinitions;

, и это должно работать ... Я думаю ... НО в документации говорится, что это неверно .

Здесь есть подсказки?

Ответы [ 2 ]

0 голосов
/ 12 июля 2020

Я не уверен, что понимаю, о чем вы спрашиваете, но вы можете определить новый интерфейс следующим образом:

interface IFirst {
    readonly foo: string;
    bah: number;
    func(args: Array<any>): number;
}

interface ISecond extends Omit<IFirst, "foo" | "func"> {
    foo: boolean;
    func: (a: number, b: number) => string;
}

const x: ISecond = {
    foo: true,
    bah: 123,
    func: (a, b) => `${a} + ${b} = ${a+b}`
}
0 голосов
/ 12 июля 2020

Просто оставлю его здесь на случай, если кто-то придет искать ответ ...

Возможна перегрузка интерфейсов ... У меня просто возникла синтаксическая проблема ...

Это НЕПРАВИЛЬНО ↓

interface FooBar {
  method: (type: 'foo', data: FooType) => void;
  method: (type: 'bar', data: BarType) => void;
}

Проблема в том, что он рассматривает его как объект (?) И говорит: method already is declared

Это ПРАВИЛЬНЫЙ способ написать его правильно ↓

interface FooBar {
  method(type: 'foo', data: FooType): void;
  method(type: 'bar', data: BarType): void;
}
...