The compiler tsc does two independent jobs: it checks your program against the types it can see, and it emits JavaScript with the types removed. Keeping those jobs apart in your head explains most of TypeScript's behavior.
Static checking
In JavaScript, user.nmae is simply undefined and Math.random < 0.5 quietly compares a function with a number (Types). The checker reads the source without running it and reports such non-exception failures.
const user = { name: "Ada", born: 1815 };
function age(person: { born: number }, year) {
return year - person.born;
}
console.log(user.nmae); // typo
if (Math.random < 0.5) console.log("heads"); // forgot the ()
const box = document.querySelector("input"); // may be null
box.value = String(age(user, 2026));basics.ts(3,40): error TS7006: Parameter 'year' implicitly has an 'any' type.
basics.ts(6,18): error TS2339: Property 'nmae' does not exist on type '{ name: string; born:
number; }'.
basics.ts(7,5): error TS2365: Operator '<' cannot be applied to types '() => number' and
'number'.
basics.ts(9,1): error TS18047: 'box' is possibly 'null'.Erased types
Run npx tsc basics.ts and you still get basics.js, with the annotations deleted and "use strict"; on top: tsc emits despite errors unless you pass --noEmitOnError. Erased types never change what the program does, and you cannot test a type at runtime; narrowing (Narrowing) relies on ordinary JavaScript checks. Erasure is also why Node.js 2,131 can run .ts files directly (Installing and Running); --erasableSyntaxOnly rejects the few constructs that emit code, such as enum and constructor parameter properties.
Downleveling
The target option names the ECMAScript version the output may use; newer syntax is rewritten. Since TypeScript 6.0 the default is es2025, so modern code passes through unchanged. ES2015 is now the floor: TypeScript 7 answers --target es5 with error TS5108: Option 'target=ES5' has been removed.
export function retries(opts?: { max?: number }): number {
const max = opts?.max;
return max ?? 2 ** 3;
}export function retries(opts) {
const max = opts === null || opts === void 0 ? void 0 : opts.max;
return max !== null && max !== void 0 ? max : Math.pow(2, 3);
}Downleveling rewrites syntax only; it does not add missing library functions such as Array.prototype.findLast.
Strictness
strict, on by default since TypeScript 6.0, switches on nine checks, chiefly noImplicitAny (the first error above) and strictNullChecks (the last); with --strict false only the middle two errors remain. Keep it on for new code; when migrating JavaScript, relax single flags in tsconfig.json (Project Configuration) and restore them gradually.