Получить тип аргумента обратного вызова метода из возвращаемого типа параметра конструктора - PullRequest
0 голосов
/ 03 августа 2020

Я работаю над SDK Webhooks . Минимальный пример кода выглядит следующим образом:

const webhooks = new Webhooks({
  secret: "secret",
  path: "/webhooks"
});
webhooks.on("issues", (event) => {
  console.log(event.name); // event type is set to { name: string, payload: any }
});

Конструктор Webhooks поддерживает параметр transform, который может изменять объект event перед его передачей обработчикам событий:

const webhooks = new Webhooks({
  secret: "bleh",
  path: "/webhooks",
  transform: (event) => Object.assign(event, { foo: "bar" })
});
webhooks.on("issues", (event) => {
  console.log(event.foo); // event type should be { name: string, payload: any, foo: string }
});

Мой вопрос: как я могу получить тип event в обратном вызове webhooks.on() на основе параметра конструктора transform?

У меня есть минимальный тестовый пример на игровой площадке TypeScript и неудачный тест в запросе на вытягивание в репозитории

Ответы [ 2 ]

1 голос
/ 03 августа 2020

Вот решение, предоставленное Andrew Branch от команды TypeScript:

type WebhookEvent<T = any> = {
    name: 'string',
    payload: T
}

type TransformMethod<T extends WebhookEvent> = (event: WebhookEvent) => T | PromiseLike<T>
type Options<T extends WebhookEvent> = {
    transform?: TransformMethod<T>
}

class Webhooks<T extends WebhookEvent> {
    public on(event: string, eventHandler: (event: T) => void) {
        // ...
    }

    constructor(options?: Options<T>) {
        // ...
    }
}

const webhooks1 = new Webhooks()
webhooks1.on('foo', event => {
    console.log(event.name)
})

const webhooks2 = new Webhooks({
    transform(event) {
        return Object.assign(event, { foo: 'bar'})
    }
})
webhooks2.on('foo', event => {
    console.log(event.foo)
})

TypeScript Playground

1 голос
/ 03 августа 2020

У вас работает что-то подобное?

type WebhookEvent<T = any> = {
    name: 'string',
    payload: T
}

type TransformMethod<T extends any> = (event: WebhookEvent) => WebhookEvent<T>
// here the change using ReturnType
type EventCallback<T extends WebhookEvent> = (event: ReturnType<TransformMethod<T>>) => void
type Options<T extends WebhookEvent> = {
    transform?: TransformMethod<T>
}

class Webhooks<T extends any> {
    public on(event: string, eventHandler: EventCallback<T>) {
        // ...
    }

    constructor(options?: Options<T>) {
        // ...
    }
}

Ключевым моментом является настройка event на тип ReturnType<TransformMethod> и добавление некоторых универсальных шаблонов здесь и там

примечания:

  • , если вы используете Object.assign, набор символов при возврате функции transform будет ослаблен - он не будет проверять, что объект
  • , если вы return a PromiseLike, событие вернет объект или объект, подобный Promise, поэтому вам придется дождаться обещания в on. На данный момент я удаляю часть обещания, чтобы было проще, но вы можете добавить ее, если адаптируете это

вот площадка

Тогда вы можете сделать

const webhooks2 = new Webhooks<{ foo: string }>({
    transform(event) {
        return Object.assign(event, { foo: 'bar'})
    }
})
webhooks2.on('foo', event => {
    event.payload.foo
    // here autocomplete works
    console.log(event.payload.foo)
})
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...