Capítulo 4 de 36
Functions are values with their own type syntax layer: how to type a callable (with or without properties, with or without new), how generics relate parameter and return types, and the special-case types (void, object, unknown, never, Function) that show up specifically around function signatures.
(a: string) => void — arrow-like syntax, parameter names are required in the type ((string) => void means a parameter literally named string of type any, not what it looks like). Name it via type GreetFunction = (a: string) => void.(someArg: number): boolean (note : not =>) alongside other properties.new (s: string): SomeObject types something invocable with new. Call and construct signatures can coexist on the same type (e.g. Date, callable both ways).<Type>) links an input type to an output/another input type — function firstElement<Type>(arr: Type[]): Type | undefined. TypeScript infers Type from the call site in most cases; multiple parameters (<Input, Output>) are fine too.<Type extends { length: number }>): restrict what a type parameter can be, unlocking property access inside the function body. A constrained generic still returns the specific input type, not just something matching the constraint — writing a function that returns a constraint-shaped literal instead of the actual input Type is a type error (correctly so: the caller was promised back the same kind of object they passed in).combine<string | number>(a, b)): needed when TS can't unify mismatched call-site types on its own.<Type>(arr: Type[]) infers a real return type; <Type extends any[]>(arr: Type) degrades to any).x?: number): the parameter's actual type inside the body is T | undefined. A default (x = 10) instead gives the body a non-optional T, since undefined args get replaced. Callers may always explicitly pass undefined to an optional param.callback: (arg: any, index?: number) => void doesn't mean "callers may omit index" — it means "the implementation may choose to invoke the callback with fewer args", so TS will reject code inside that callback that unconditionally uses index as a number. Rule: never write an optional parameter in a callback type unless you intend to call it without that argument. (JS just ignores extra call-site arguments, so a plain, fully-typed parameter list is almost always what you want instead.)makeDate(timestamp) vs makeDate(m, d, y)). The implementation signature must be compatible with (a superset covering) every overload; it is invisible to callers, so writing only the implementation signature with optional params does not make it callable with fewer args unless overloads say so explicitly.len(cond ? "a" : [1]) fails even though both len(string) and len(any[]) overloads exist individually).this parameters: JS forbids a real parameter named this, so TypeScript repurposes that syntax slot to declare the function's expected this type — function (this: User) { return this.admin }. Required for callback-style APIs where the caller controls this binding; only works with function, not arrow functions (arrows lexically capture this and can't redeclare it).void: inferred return type when a function has no return, or bare return; — distinct from undefined even though a void JS function runtime-returns undefined.object: any non-primitive (excludes string/number/bigint/boolean/symbol/null/undefined) — not the same as the near-useless global Object, and not the same as the empty-object-type {}. Function values count as object.unknown: the type-safe counterpart to any — accepts any value, but nothing can be done with an unknown value until it's narrowed/asserted. Good for "accepts anything" parameters and "returns some value the caller must check" returns (e.g. JSON.parse wrapped as unknown).never: return type of a function that always throws or never terminates; also what a fully-narrowed-away union collapses to.Function: the global type exposing bind/call/apply; calling a Function-typed value returns any (an "untyped function call" — usually avoid; prefer () => void if you just need "any callable, not intending to invoke it")....m: number[]): implicitly any[] if unannotated; explicit annotation must be T[]/Array<T>/a tuple type.number[] into a fixed-arity function like Math.atan2(...args) fails type-checking because the array's length isn't statically known. Fix with as const (freezes it to a fixed-length tuple).function sum({ a, b, c }: { a: number; b: number; c: number }), or via a named type alias for readability.() => void accepts an implementation that does return a value (e.g. const f: voidFunc = () => true is legal — the return value is just ignored/typed as void on the caller's side). This is deliberate, so patterns like arr.forEach(el => dst.push(el)) type-check even though push returns number. The exception: a function declared literally as function f(): void { return true } (return type written directly on the function, not via a variable's contextual type) is a hard error — that specific form does enforce "must not return a value".function longest<Type extends { length: number }>(a: Type, b: Type) {
return a.length >= b.length ? a : b;
}
const longerArray = longest([1, 2], [1, 2, 3]); // number[]
const longerString = longest("alice", "bob"); // "alice" | "bob"
{ length: number }) rather than a specific type — usable across arrays and strings alike, while still returning the caller's exact input type.function makeDate(timestamp: number): Date;
function makeDate(m: number, d: number, y: number): Date;
function makeDate(mOrTimestamp: number, d?: number, y?: number): Date {
return d !== undefined && y !== undefined ? new Date(y, mOrTimestamp, d) : new Date(mOrTimestamp);
}
| Type | Meaning | Contrast |
|---|---|---|
void | inferred no-return / explicit "returns nothing" | not the same as undefined |
object | any non-primitive | not Object (global type, rarely useful), not {} |
unknown | anything, but unusable until narrowed | safer alternative to any |
never | a value that can't occur (throws, infinite loop, exhausted union) | assignable to everything; nothing (but never) assignable to it |
Function | any callable (has bind/call/apply) | calling it returns any — usually avoid |
unknown is almost always the right choice over any for "accepts/returns something the caller must check" — it forces narrowing before use instead of silently disabling checks.as const before spreading them into fixed-arity calls (Math.atan2(...args)) — otherwise TS only knows "array of N", not the exact length.unknown and never both interact directly with narrowing/exhaustiveness checking.this parameter typing extends into method definitions and this-based type guards.