Anropa Readonly-funktion i Typescript
Jag bygger en app med en oföränderlig datamodell och jag har nått följande återvändsgränd:
Jag har en funktion som är lagrad som oföränderlig som i följande exempel:
const f: Readonly<() => void> = () => {};
f();
När jag anropar f får jag följande fel:
This expression is not callable.
Type 'Readonly<() => void>' has no call signatures. (2349)
Jag förstår inte vad som omvandlas av Readonly som producerar denna effekt.
Att kasta tillbaka till mutable verkar inte vara en lösning. Detta ger samma fel:
export type Mutable<T> = {
-readonly [K in keyof T]: T[K];
};
(f as Mutable<typeof f>)();
Jag vill förstå grundorsaken till detta problem, inte nödvändigtvis leta efter lösningar, som att kasta till exakt funktionstyp eller inte använda Readonly på funktioner.
Länk till lekplatsen.
Svar #1
Du kan använda Readonly<Function> för att säga att funktionens egenskaper (t.ex. apply, bind, call...) är skrivskyddade, och en snittypstyp för att behålla funktionens anropssignatur.
type ReadonlyFunction<F extends Function> = Readonly<Function> & F;
const f: ReadonlyFunction<() => void> = () => {};
// OK
f();
// Error: Expected 0 arguments, but got 2.
f(1, 2);
// Error: Cannot assign to 'apply' as it is a readonly property.
f.apply = 'foo';
Lekplatslänk
Anledningen till varför Readonly<() => void> inte fungerar verkar vara att Readonly är en mappad typ, så den mappar egenskaperna hos typen () => void, men inte anropssignaturen.
Det visar sig att typen () => void inte har några egenskaper, så t.ex. keyof (() => void) är never, och { [K in keyof (() => void)]: any } är {}.
