javascript - „Dieser Ausdruck ist nicht aufrufbar“ in Typescript mit Typverengung
Ich definiere eine Funktion mit der gleichen Signatur wie Reacts useState:
declare function useState<S>(
initialState: S | (() => S),
): [S, React.Dispatch<React.SetStateAction<S>>];
Hier ist ein Teil der Funktion:
function foo<T>(initialState: T | (() => T)) {
typeof initialState === 'function' ? initialState() : initialState;
}
Ich bekomme diesen Fehler:
This expression is not callable.
Not all constituents of type '(() => T) | (T & Function)' are callable.
Type 'T & Function' has no call signatures.(2349)
Bedeutet T & Function nicht, dass T eine Funktion ist, also aufrufbar? Wie kann ich das ohne erzwungene Typumwandlungen beheben?
Antwort #1
Der Typ kann erfolgreich mithilfe von initialState instanceof Function eingegrenzt werden:
function foo<T>(initialState: T | (() => T)) {
initialState instanceof Function ? initialState() : initialState;
}
Bearbeiten: Interessanterweise kompiliert das, aber es wird bei einigen Randfällen fehlschlagen. Zum Beispiel, wenn initialState Object.create(Function.prototype) ist. Dies ist eine Instanz von Function, ist aber nicht aufrufbar.
Antwort #2
Der einfachste Weg wäre, dem Compiler zu sagen, dass initialState eine Funktion ist, wenn typeof initialState 'function' ist.
function foo<T>(initialState: T | (() => T)) {
if (isFunction(initialState)) {
initialState();
} else {
initialState;
}
}
function isFunction<T>(f: T | (() => T)): f is (() => T) {
return typeof f === 'function';
}
