TYPESCRIPT / CHAPTER 08
Function compatibility and callback promises
AdvancedMake callback types reflect every call the implementation may make.
By the end of this chapter
- Read parameter and result compatibility
- Avoid unsafe narrowing of callback inputs
- Distinguish ignored results from asynchronous completion
The idea
A callback contract describes what the caller may pass and what the callback must support. Under strictFunctionTypes, a function accepting only one narrow subtype cannot safely stand in for a function that may receive a broader union. Use function-valued properties or plain function types in these examples; method syntax has additional variance compatibility rules.
A callback parameter declared optional means its caller is allowed to omit that argument. Do not mark a parameter optional merely because some callback implementations ignore it. TypeScript also permits a value-returning function where a context expects void, because the result is ignored. That does not make an asynchronous callback automatically awaited. If completion matters, express Promise<void> and await it explicitly.
function each(values: number[], visit: (value: number, index: number) => void) {
values.forEach((value, index) => visit(value, index));
}
const seen: number[] = [];
each([4, 7], value => { seen.push(value); });
console.log(seen.join(","));4,7
A callback may ignore extra supplied arguments without requiring the contract to make them optional.
Try it yourself
Write an asyncEach helper whose callback returns Promise<void> and whose own promise waits for every required invocation.
Use your own editor for this exercise. Runnable challenges on CodeQuest are available for JavaScript, Python, and SQL.
CHECK YOUR UNDERSTANDING