You add a type after a colon. TypeScript can infer many types, so you annotate where it adds clarity or where inference isn't possible.
ts
: = ;
name = ;
(): {
name.(times);
}
: [] = [, , ];
: { : ; : } = { : , : };
You add a type after a colon. TypeScript can infer many types, so you annotate where it adds clarity or where inference isn't possible.
: = ;
name = ;
(): {
name.(times);
}
: [] = [, , ];
: { : ; : } = { : , : };
function add(a: number, b: number) { return a + b; } // inferred return: number
function load(): Promise<User> { ... } // explicit — documents the contract
Return types are inferred, but annotating them on exported/public functions is good practice: it documents intent and catches mistakes inside the function (if you accidentally return the wrong thing, the error points at the function, not its callers).
function log(msg: string): void {} // returns nothing
function fail(): never { throw new Error(); } // never returns normally
const fn: (x: number) => string = ...; // function type annotation
The rule of thumb: annotate function signatures (parameters and public return types) explicitly, let local variables be inferred. This keeps code concise while making the contracts at function boundaries clear and checked.