Basic Types
string, number, boolean, arrays, tuples, any, unknown, and never — TypeScript's type system foundation
Knowledge Debt detected
You can study this freely — but your score may plateau if these foundations have gaps. The Mastery badge requires them to be solid.
Explanation
TypeScript adds static types to JavaScript. You annotate variables with : Type and the compiler catches type mismatches before your code runs.
Primitive types:
typescript let name: string = 'Alice'; let age: number = 30; let active: boolean = true; TypeScript infers types from initializers — you can omit the annotation when it's obvious: typescript let name = 'Alice'; // inferred: string let age = 30; // inferred: number
Arrays and Tuples:
typescript // Arrays — two equivalent syntaxes let scores: number[] = [95, 87, 92]; let tags: Array<string> = ['typescript', 'react']; // Tuple — fixed length, each position has its own type let point: [number, number] = [10, 20]; let entry: [string, number] = ['age', 30]; // entry[0] is string, entry[1] is number — order matters
`any`, `unknown`, and `never`:
| Type | Meaning | Safe? | |---|---|---| | any | Opts out of type checking entirely | No — avoid | | unknown | Unknown type, must narrow before use | Yes | | never | Value that can never occur | — (used in exhaustive checks) |
// any — no type safety (avoid)
let x: any = 'hello';
x = 42; // no error
x.foo.bar(); // no error, but crashes at runtime
// unknown — must check type before use
let val: unknown = fetchData();
if (typeof val === 'string') {
console.log(val.toUpperCase()); // safe — narrowed to string
}
// never — unreachable code / exhaustive checks
function fail(msg: string): never {
throw new Error(msg);
}`void` — for functions that return nothing: ``typescript function log(msg: string): void { console.log(msg); // no return statement (or returns undefined) }
Examples
Type annotations and inference
TypeScript infers types from initializers — annotations are only needed when the type isn't obvious from context.
// Explicit annotations
let username: string = 'alice';
let score: number = 100;
let isAdmin: boolean = false;
// Inferred — TypeScript figures it out from the value
let greeting = 'Hello, World!'; // string
let count = 0; // number
// Arrays
let ids: number[] = [1, 2, 3];
let names: string[] = ['Alice', 'Bob'];
// Tuple — position matters
let coordinates: [number, number] = [51.5, -0.1];
let record: [string, number, boolean] = ['Alice', 30, true];
// Type error caught at compile time (not runtime)
// username = 42; // Error: Type 'number' is not assignable to type 'string'any vs unknown — why it matters
Prefer `unknown` over `any` — it forces you to narrow the type before using it, keeping type safety intact.
// any — dangerous: no checks at all
function processAny(val: any) {
return val.toUpperCase(); // TypeScript won't complain — but crashes if val is a number
}
// unknown — safe: force the caller to check the type first
function processUnknown(val: unknown) {
// val.toUpperCase(); // Error: Object is of type 'unknown'
if (typeof val === 'string') {
return val.toUpperCase(); // OK — narrowed to string
}
return String(val);
}
// never — used in exhaustive switch statements
type Shape = 'circle' | 'square';
function area(shape: Shape): number {
switch (shape) {
case 'circle': return Math.PI * 5 ** 2;
case 'square': return 5 * 5;
default:
const _exhaustive: never = shape; // Error if a case is missing
return _exhaustive;
}
}How well did you understand this?
Next in TypeScript
Interfaces & Type Aliases