Basic Types
TypeScript extends JavaScript with a rich type system. This chapter covers the types you will use most often.
Primitive Types
TypeScript supports the same primitives as JavaScript, with explicit annotations:
let title: string = 'JS Code Camp';
let count: number = 42;
let isActive: boolean = true;
let nothing: null = null;
let notDefined: undefined = undefined;
// bigint and symbol (ES2020+)
let big: bigint = 100n;
let id: symbol = Symbol('id');
Type Inference
When you assign a value, TypeScript often infers the type automatically:
let city = 'Seattle'; // inferred as string
city = 'Portland'; // OK
// city = 123; // Error
const PI = 3.14159; // inferred as number, readonly by const
Explicit annotations are useful when there is no initial value or you want a wider type:
let input: string; // no initializer — annotation required
input = 'hello';
Arrays
Two equivalent syntaxes for arrays:
let scores: number[] = [90, 85, 88];
let names: Array<string> = ['Alice', 'Bob'];
// Readonly arrays prevent mutation
const tags: readonly string[] = ['js', 'ts'];
// tags.push('node'); // Error
Tuples
Tuples are fixed-length arrays where each position has a known type:
let pair: [string, number] = ['Alice', 25];
let rgb: [number, number, number] = [255, 128, 0];
let point: [number, number] = [10, 20];
Access tuple elements by index — TypeScript knows the type at each position:
const [name, age] = pair;
console.log(name.toUpperCase()); // string methods available
console.log(age.toFixed(1)); // number methods available
Enums
Enums assign names to numeric or string constants:
enum Direction {
Up,
Down,
Left,
Right
}
let heading: Direction = Direction.Up;
console.log(heading); // 0
enum Status {
Pending = 'PENDING',
Active = 'ACTIVE',
Done = 'DONE'
}
function setStatus(s: Status) {
console.log(s);
}
setStatus(Status.Active); // "ACTIVE"
String enums produce readable values at runtime. Many teams prefer union types instead (covered later).
any, unknown, and never
let flexible: any = 'hello';
flexible = 42; // no error — avoid any in production code
let userInput: unknown = getData();
// Must narrow before use:
if (typeof userInput === 'string') {
console.log(userInput.toUpperCase());
}
function fail(msg: string): never {
throw new Error(msg); // never returns
}
Use unknown instead of any when the type is not yet known — it forces you to check before use.
Object Types
Inline object type annotations describe shape:
let user: { name: string; age: number; email?: string } = {
name: 'Alice',
age: 30
};
user.email = '[email protected]'; // optional property
For reusable shapes, prefer interfaces or type aliases — covered in the next chapter.
Summary
| Type | Example | Use case |
|---|---|---|
| Primitives | string, number, boolean |
Single values |
| Arrays | number[] |
Collections |
| Tuples | [string, number] |
Fixed structure |
| Enums | Status.Active |
Named constants |
unknown |
Safe alternative to any |
External input |
Next, we apply these types to functions and define object contracts with interfaces.