Комментарии 9
1. Создаем файл lib_extends.dom.d.ts
/** Первый вариант */
interface CustomMessageEvent<T = any> extends MessageEvent {
data: T;
}
interface Worker {
addEventListener<T>(message: string, handler: (message: CustomMessageEvent<T>) => any, options?: boolean | AddEventListenerOptions): any;
}
/** Второй вариант */
interface Worker {
addEventListener<T = any>(message: string, handler: (message: Omit<MessageEvent, "data"> & {data: T}) => any, options?: boolean | AddEventListenerOptions): any;
}
2. Добавляем в tsconfig.json в секцию include строку
"include": [
"./путо до lib_extends.dom.d.ts",
]
3. И далее в коде проекта используем
const worker = new Worker(...);
worker.addEventListener<string>("message", (message => {
message.data // (property) data: string
}))
В моих проектах используется такой подход:
// globals.d.ts
interface TypedMessageEvent<T> extends MessageEvent {
data: T;
}
interface TypedWorkerEventMap<T, E = T> extends AbstractWorkerEventMap {
"message": TypedMessageEvent<T>;
"messageerror": TypedMessageEvent<E>;
}
interface TypedWorker<Input, Output> extends Worker {
postMessage(message: Input, transfer: Transferable[]): void;
postMessage(message: Input, options?: PostMessageOptions): void;
addEventListener<K extends keyof TypedWorkerEventMap<Output>>
(type: K, listener: (this: TypedWorker<Input, Output>, ev: TypedWorkerEventMap<Output>[K]) => any, options?: boolean | AddEventListenerOptions): void;
}
Это позволяет описать как все входящие так и исходящие сообщения
type MessageStart = 'start';
type MessageStop = 'stop';
type MessageProgress = 'progress'
type MessageInput = MessageStart | MessageStop
type MessageOutput = MessageProgress
const w = new Worker() as TypedWorker<MessageInput, MessageOutput>
w.addEventListener('message', m => {
m.data // 'start' | 'stop'
})
w.postMessage('some') // Type "some" is not assignable to type "MessageProgress"
Мне всегда было интересно, а в чем преимущество генерации кода из json перед непосредственно кодом как есть?
Не совсем понял ваш вопрос
Почему просто не хранится файл src/lib/d.ts в котором можно просто напрямую поменять код? Зачем вносить изменения в JSON из которых код сгенерируется?
Ну, то есть я понимаю, что раз так делают, в этом есть какое-то преимущество, вот мне и интересно какое.
Если коротко — для автоматизеции и уменьшения ручной работы.
Если чуть подробнее:
- Источником всех типов являются .widl файлы. Они автоматически вытягиваются из браузера Edge. То есть, все веб интерфейсы пишутся не вручную а берутся из того, что имплементировано в браузере. Вот, описание MessageEvent, например.
Так можно быстро и легко отслеживать все изменения в спецификациях веб-платформы. - Многие такие интерфейсы должны быть представлены в нескольких библиотеках. Чтобы не приходилось согласовывать описание одного и того же интерфейса в разных библиотеках он вынесен в отдельный файл, а уже оттуда записывается в нужные библиотеки.
А в формате JSON просто описаны дополнительные инструкции о том, как конвертировать widl в ts
Спасибо что потратили свое время и сделали Typescript типы немножко лучше для остальных пользователей!
Как я закрыл трехлетний issue в TypeScript