Hvordan gjøre utsøkte typevakter i TypeScript
La oss definere TS-typer slik:
interface Result<T, E> {
isOk(): this is Ok<T>;
isErr(): this is Err<E>;
}
interface Ok<T> extends Result<T, never> {
value: T;
isOk(): true;
isErr(): false;
}
interface Err<E> extends Result<never, E> {
error: E;
isOk(): false;
isErr(): true;
}
Dette er fint fordi Result-grensesnittet foreskriver strukturen til en Ok og Err. Men når jeg gjør en sjekk som dette:
if (result.isOk()) {
// A
}
// B
I del B er typen til result fortsatt Result, ikke Err. For å oppnå dette, må jeg definere typene annerledes:
interface Ok<T> {
value: T;
isOk(): true;
}
interface Err<E> {
error: T;
isOk(): false;
}
type Result<T, E> = Ok<T> | Err<E>;
Dette løste problemet. Men nå er verken Ok eller Err av typen Result, og jeg har ikke ett felles grensesnitt som sier hvilke metoder Ok og Err begge bør arve.
Mitt spørsmål: finnes det en måte å kombinere fordelene ved begge disse løsningene på? Å ha uttømmende typebeskyttelser og samtidig ha et felles grensesnitt som både Ok og Err utvider?