typescript - Finnes det en 'ikke promise'-type i typescript?
Jeg skriver TypeScript og vil lage noe som Exclude<void, Promise<void>>, som tillater void men ikke tillater Promise<void>.
type A = (a: number) => Promise<void>
type B = (a: number) => void
declare let a: A
declare let b: B
// it does not cause type error
b = a
// what i want to do...
// but it is identical to B
type C = (a: number) => Exclude<void, Promise<void>>
Imidlertid ser Exclude<void,Promise<void>> ut til å være identisk med void.
Er det noen måter å lage en type som dette på?
Svar #1
Som TypeScript-dokumentasjonen sier det:
voider litt som motsatsen tilany: fraværet av å ha noen type i det hele tatt.
Siden det er fraværet av å ha noen type, gir det ingen mening å utelukke noe fra det.
Grunnen til at du kan tilordne type A til type B er at, enkelt sagt, kan enhver funksjon være void dersom du bare ignorerer returtypen. For det en returtype void egentlig betyr, er at du ikke kan bruke returverdien. Og denne egenskapen er kompatibel med enhver funksjon, du må bare ignorere hva den enn returnerer.
Dette påvirker ikke bare Promise<void>, men alle returtyper:
declare let voidFunction: (a: number) => void;
declare let promiseFunction: (a: number) => Promise<void>;
declare let numberFunction: (a: number) => number;
declare let stringFunction: (a: number) => string;
declare let undefinedFunction: (a: number) => undefined;
voidFunction = promiseFunction; // no error
voidFunction = numberFunction; // no error
voidFunction = stringFunction; // no error
voidFunction = undefinedFunction; // no error
Merk imidlertid at det motsatte ikke er sant:
promiseFunction = voidFunction; // error
numberFunction = voidFunction; // error
stringFunction = voidFunction; // error
undefinedFunction = voidFunction; // error
Jeg tror en bedre løsning for ditt tilfelle faktisk ville være å bruke undefined som returtype i stedet for void:
undefinedFunction = promiseFunction; // error
undefinedFunction = numberFunction; // error
undefinedFunction = stringFunction; // error
Problemet med dette er imidlertid at når du erklærer en funksjon med returtype undefined, må du faktisk ha en return undefined;-setning, noe du sannsynligvis ikke ønsker.
For å løse dette, tror jeg undefined | void ville være et godt kompromiss for en returtype:
declare let undefinedVoidFunction: (a: number) => undefined | void;
undefinedVoidFunction = promiseFunction // error
undefinedVoidFunction = numberFunction // error
undefinedVoidFunction = stringFunction // error
undefinedVoidFunction = undefinedFunction // no error
undefinedVoidFunction = voidFunction // no error
Lekeplass
Svar #2
For tilfeller hvor du virkelig trenger en not promise-type, prøv følgende:
type C<T> = (a: number) => T extends Promise<any> ? never : T;
