Oct 17, 2021 10:30
У нас тут есть сторонний HTTP-сервис, возвращающий либо { success: true } либо { error: 42, description: "because" }. Ну и по openapi.yaml генерится в таком духе декларация (за правильность кейвордов не ручаюсь):
export interface Foo {
bar:
| { success: boolean }
| { error: number, description: string }
}Ну и есть такой вот код:
const foo: Foo = getFoo()
if ('error' in foo) {
throw new Error(foo.description)
}
console.log(foo.success)Ну и это работает как GADT pattern matching, только без гадтов и паттернов :) То есть внутри ифа нельзя напечатать foo.success - будет ошибка компиляции, а после ифа нельзя доступиться к error или description, поскольку компилятор видит, что мы сделали достаточно рантайм-сравнений для сужения типа foo в разных участках кода до одной ветки (то, что throw обрывает control flow - он тоже видит).
И тут интересно, ввиду того что спецификация кросс-языковая, как с этой ситуацией (типизированная работа с вариантами ответа) предлагает справляться OpenAPI/Swagger кодогенерация для других языков.
Там кстати есть тонкости в схеме, что надо лепить
additionalProperties: false
required:
- success, иначе мы говорим, что все поля нуллабле и он генерит не то, что мы имеем ввиду.
Ну и это конечно непонятно как на наших гребцов ляжет. Разрешу им везде as unknown as any писать чтобы батька потом чинил :)
fp,
все пидарасы а я,
programming