Typescript — значение силы, которое должно быть свойством интерфейса

#typescript #discord.js

Вопрос:

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

В этом примере ClientEvents определяются discord.js , EventInterface определяют формат объекта/класса , используемого на фабрике, и MessageCreateEvent являются примером реализации.

Я хочу заставить name значение реализованного класса быть ключом ClientEvent (как в приведенном ниже коде, но это не работает), и я хочу ввести аргументы execute , соответствующие типу данного ключа ClientEvent . Например, если name есть messageCreate , и DontKnowType должно быть a Message .

 type Message = unknown;
type DontKnowType = unknown;

interface ClientEvents {
  messageCreate: [message: Message];
}


interface EventInterface<T extends keyof { [x: string]: ClientEvents}> {
    name: T,
    execute: (interactObject: DontKnowType) => Promise<void | undefined>;
}

class MessageCreateEvent implements EventInterface<'messageCreate'> {
    public name = 'messageCreate';

    public async execute(interactObject: DontKnowType): Promise<void | undefined> {
        console.info(`Message from ${interactObject?.user.tag}`);
    }
}
 

Вы можете мне помочь, пожалуйста ?

Комментарии:

1. Пожалуйста, приведите воспроизводимый пример, в котором определены все типы

2. public name: keyof ClientEvents = 'messageCreate' ? Не совсем понятно, что вам здесь нужно.

3. Я хочу способ заставить interactObject быть того же типа ClientEvents[this.name] .

Ответ №1:

Будет намного понятнее, если вы приведете примеры или комментарии о том, как ваш пример должен работать, а как нет.

Но я изменил ваш код, чтобы выполнить проверку классов событий Message** EventInterface и заставить имя быть частью интерфейса событий Message**.

 interface EventInterface<T extends keyof ClientEvents> {
  name: T
  execute: (...args: ClientEvents[T]) => Promise<void>;
}
class MessageCreateEvent implements EventInterface<'messageCreate'>{
    public name = 'messageCreate' as const;
    public async execute(message: Message): Promise<void> {
        console.info(`Message from ${message!.user!.tag!}`);
    }
}
 

полный пример на игровой площадке

Это то, что вы ищете?

Комментарии:

1. Это явно то, чего я хочу, спасибо ! Я не мог найти его сам, потому что не думал добавлять ... раньше args (это потому ClientEvents , что формат похож messageCreate: [message: Message] и нет messageCreate: Message ?

2. Это зависит… messageCreate: [message: Message] позволяет описать все аргументы функции, и с messageCreate: Message помощью этого вы можете определить тип только для одного аргумента: execute: (arg0: ClientEvents[T], ...args: any[]) => Promise<void>;