Is it possible to type a callback function in Typescript that encodes the following 2 invariants in the type system:
- if err == null then x is of type
T - if err != null then x must not be referenced (
never?)
type Callback<T> = {
(error: null, value: T): void;
(error: Error): void;
};
// The function that takes the typed callback.
function incrementAsync(x: number, cb: Callback<number>): void {
if (x === 0) {
return cb(new Error());
}
cb(null, x + 1); // should type-check
cb(new Error()); // should type-check
cb(new Error(), 1) // should fail type-check
cb(null); // should fail type-check
}
Here's the function signature that I really want:
// Error: This overload signature is not compatible
// with its implementation signature.
function definedCb1(e: Error);
function definedCb1(e: null, x: number): void {}
incrementAsync(10, definedCb1); // error with strictNullChecks
Here's a looser function signature that type checks
// BAD because types are too loose but this passes type-check.
function definedCb2(e: Error|null, x?: number): void {
if (e === null) {
// Is there a way to type this function, so the ! is not necessary?
console.log(x! + 1);
return;
}
// error because x might be undefined.
console.log(x + 2);
}
incrementAsync(20, definedCb2) // Works
Typescript Playground Link enable strictNullChecks and noImplicitAny.
function logNum(error: Error | null, x?: number): void {...if (error == null)byif (error !== null)if i understand what you want to doxhas typeTor 2. err != null andxmust not be referenced.