Functions and generics
Type function parameters
Put type annotations on a function boundary so invalid calls fail before the function body executes.
Function parameters are boundaries. Inside the body you control the code. At the boundary, anyone can call with anything. So the parameter list is where you write down what callers are allowed to pass:
function greet(name: string, times = 1) {
return name.repeat(times)
}
Two things happen here. name: string is an explicit annotation. The default value = 1 lets TypeScript infer times as a number without one. The default also makes the parameter optional: leave it out and the function uses 1.
Both of these calls are valid:
greet('Ada')
greet('Ada', 3)
Pass a boolean where the name goes and the call fails before the function runs:
greet(true, 3)
error TS2345: Argument of type 'boolean' is not assignable to parameter of type 'string'.
Compare that with plain JavaScript. greet(true, 3) would reach .repeat() and throw at runtime, possibly in production. The annotation moves the failure to the call site, at compile time, with the caller’s file and line in the message.
Parameters need annotations
Unlike variables, parameters usually need explicit types. There is no initial value to infer from, because the value arrives when someone calls the function. Under strict checking, an unannotated parameter is an error:
function shout(name) {
return name.toUpperCase()
}
error TS7006: Parameter 'name' implicitly has an 'any' type.
TypeScript is telling you it would have to fall back to any, and strict mode refuses to do that silently. Add the type.
Optional parameters
Mark a parameter with ? when callers can genuinely leave it out:
function greet(name: string, title?: string) {
return title ? `${title} ${name}` : name
}
Inside the function, title is string | undefined. The body has to handle both cases. That is the deal you make when you accept an optional argument. Here the truthiness check does it, and greet('Lovelace', 'Countess') returns 'Countess Lovelace'.
Order matters too. Optional parameters must come after required ones. A call like greet(undefined, 'Ada') has no clean way to skip a leading parameter, so TypeScript does not allow a required parameter after an optional one.
Do not make things optional to silence errors
When a call site fails because it lacks a value, the tempting fix is to add a ? to the parameter. Do not do that. It moves the same problem into every use inside the function: each read of the parameter now needs an undefined check. And every other caller, who did have the data, pays for it too.
If one caller does not have the data, the fix belongs at that caller. The signature everyone shares should tell the truth about what the function needs.
Try this on your own: add an optional punctuation parameter to greet() with a default of '!'. Hover over it inside the function and check what TypeScript inferred.
Lesson completed