Inference and explicit boundaries
Objective
Distinguish inferred local types from annotated function contracts. This course assumes you can already write JavaScript functions, loops, arrays, and objects.
Distinguish inferred local types from annotated function contracts.
Explanation
TypeScript checks JavaScript before execution. A local initializer usually supplies enough information for inference; a function parameter needs a declared contract. Types disappear from emitted JavaScript, so a number annotation does not validate an incoming JSON value.
Keep annotations at public boundaries and let obvious locals infer their types. Strict checking catches incompatible assignments but does not prove an algorithm computes the right answer.
Runnable worked example
Compile this complete example with strict checking. The practice editor supplies the function calls; return a value rather than printing it.
function double(value: number): number {
return value * 2;
}
const result = double(0);
Expected value of result:
0
Types document the boundary; the expression determines runtime behavior.
Common mistakes
Do not replace a failing check with any. Separate a compile-time guarantee from runtime input validation.
Guided practice
Explain each parameter and return type in the example. Predict its empty or boundary case before running it. Change one annotation to an incompatible type and read the compiler diagnostic; then restore it and change the implementation to create a behavioral bug. Explain why the two failures require different checks.
Independent practice
Recap
Distinguish inferred local types from annotated function contracts. Strict checking protects type relationships; explicit runtime checks protect external-data boundaries. Keep tests for behavior and non-mutation alongside both.