DAY 27 OF 30
Function types and overloading
Yesterday, in one sentence
Record, ReturnType, Parameters and Awaited do?Record<K, T> builds an object type from a set of keys K and a single value
type T. ReturnType<T> gives the return type of a function type.
Parameters<T> gives a tuple type of that function's parameters. Awaited<T>
gives the type a promise resolves to.
Did you say:
- ✓`Record<K, T>` builds an object type with the keys `K` and the value type `T`
- ✓`ReturnType<T>` gives the return type of a function type
- ✓`Parameters<T>` gives a tuple type of a function's parameters
- ✓`Awaited<T>` gives the type a promise resolves to
Interview question
Narrowing is TypeScript reducing a value from a wider type to a more specific one
inside a branch. Type guards are the runtime checks that cause it, like typeof,
in and Array.isArray. You can also write a custom type guard, a function whose
return type is a type predicate such as value is Hero.
Did you say:
- ✓narrowing is TypeScript reducing a value to a more specific type inside a branch
- ✓type guards are the runtime checks that cause it, such as `typeof` and `in`
- ✓a custom type guard is a function returning a type predicate
A function type is a type that describes the shape of a function: it specifies its parameters and return type. It can be named and stored in a type aliasType Alias, which makes it reusable.
Attack below describes a function that takes one string parameter and returns a
number. Annotating punch with it applies that shape, so target is a string and
the function has to return a number.
// type TypeName = (param: type) => returnType
type Attack = (target: string) => number;
const punch: Attack = (target) => target.length;
target needs no annotation of its own, because TypeScript reads it from Attack.
This is how callbacks and React props get typed.
In TypeScript a signature is a function's parameters and return type written without a body. Function overloading is writing more than one signature for the same function, so it can return a different type depending on what it is given. Those extra signatures are called overload signatures, and they sit directly above the function, each one a line ending in its return type.
function summon(name: string): string; // overload signature
function summon(count: number): string[]; // overload signature
// implementation signature: covers both of the above, not offered to callers
function summon(input: string | number): string | string[] {
return typeof input === "number" ? Array(input).fill("hero") : input;
}
const one = summon("Logan"); // string
const team = summon(3); // string[]
At runtime there is only one function, the implementation, and every call goes to it. The overload signatures exist for TypeScript, which picks the first one matching the arguments and types the call from that.
Without them, both calls would return string | string[] and the caller would have to
narrow.
The catch is that an argument has to match one overload signature on its own. A value typed as the union of both matches neither.
const input: string | number = 3;
summon(input);
// ❌ No overload matches this call
Check yourself
result here?
function find(id: number): string
function find(id: string): string[]
function find(id: number | string): string | string[] {
return typeof id === "number" ? "one" : ["many"]
}
const result = find("logan")
The argument is a string, so TypeScript picks the second overload signature and the call is typed as string[]. The implementation signature is not offered to callers, so the wider string | string[] is never what a caller gets.
Writing several signatures for a single function, each pairing a set of parameters with its own return type. One function definition sits underneath and covers all of them, but its signature is not offered to callers. TypeScript picks the first signature that matches the arguments at the call site.
Did you say:
- ✓several signatures for one function
- ✓each pairs a set of parameters with its own return type
- ✓one function definition underneath, its signature not offered to callers
- ✓TypeScript picks the first signature that matches the call