typescript - Inte alla beståndsdelar av typen 'number | function' kan anropas
Tänk på en enkel funktion som denna:
export const add = (num?: number) => {
const adder = (n: number) => {
if (!n) {
return num;
}
num = (num && num + n) || n;
return adder;
};
return adder;
};
Exempel på användning:
const result = add(1)(2)(3)() // => 6
När add anropas kommer den antingen att returnera nästa funktion som tar ett annat nummer, eller en slutlig summa om inget nummer skickas.
Detta skulle fungera som förväntat i vanlig JS, men för TypeScript kommer detta att orsaka ett fel:
Detta uttryck kan inte anropas. Inte alla beståndsdelar av typen 'number | ((n?: number | undefined) => (x?: number | undefined) => number | ...)' kan anropas. Typen 'number' har inga anropssignaturer.ts(2349)
Detta beror på att TS inte kan avgöra om nästa iteration returnerar en funktion eller ett nummer.
Fråga :
Hur man skriver denna funktion korrekt, så att TS inte kastar ett fel?
Svar #1
Det är absolut möjligt att beskriva anropssignaturen för add() så att de som anropar ser det önskade beteendet. Tyvärr kommer TypeScript-kompilatorn inte att kunna verifiera att implementeringen av add() uppfyller denna anropssignatur; den skulle behöva vara smartare när det gäller överlagringsimplementeringar eller beteendet hos generiska villkorstyper för att kunna göra det. Detta innebär att vi behöver åtminstone en typkonvertering eller en liknande teknik för att släppa typkontroller för att undertrycka kompilatorfel.
Hur som helst, låt oss säga att add är en funktion av en typ jag kommer att kalla Adder:
interface Adder {
(n: number): Adder;
(n?: undefined): number
}
En Adder är en överlagrad funktion med två anroppssignaturer; antingen anropar du den med ett number, i vilket fall en annan Adder returneras, eller så anropar du den utan argument (eller jag antar med ett undefined), i vilket fall du får ett number. Nu kan vi hävda att add är en Adder:
const add = ((num?: number) => {
const adder = (n: number) => {
if (!n) {
return num;
}
num = (num && num + n) || n;
return adder;
};
return adder;
}) as Adder; // <-- assertion
Och sedan beter sig saker som förväntat:
const result = add(1)(2)(3)() // no error now
console.log(result); // 6
Playground-länk till kod
