Basic Types
Why basic types matter
TypeScript’s type system starts with a small set of basic types. These types make your intent explicit and allow the compiler to catch common mistakes early. In production code, basic types are not “beginner only” knowledge — they are the building blocks you use everywhere: data models, API contracts, and function boundaries.
string
The string type represents textual data. Using string prevents accidental numeric operations, invalid comparisons, and misused inputs.
let username: string = "ozan"; username = "admin"; // OK username = 123; // Type error
number
The number type represents all numeric values in JavaScript, including integers and floating-point values. TypeScript uses a single number type to match the JavaScript runtime.
let price: number = 199.99; price = 250; // OK price = "250"; // Type error
boolean
The boolean type represents true/false values. It helps prevent accidental string-based truthiness and unclear control flow.
let isPublished: boolean = false; isPublished = true; // OK isPublished = "true"; // Type error
null and undefined
In JavaScript, null and undefined are common sources of runtime errors. In strict TypeScript projects, you must handle them intentionally. This reduces “cannot read property of undefined” type failures in production.
let avatarUrl: string | null = null; avatarUrl = "https://example.com/a.png"; // OK avatarUrl = null; // OK
any
The any type disables type checking. It is sometimes useful during quick migrations or when typing extremely dynamic data, but in production it should be treated as a code smell. Overusing any removes the main benefits of TypeScript.
let payload: any = { ok: true };
payload = "anything"; // allowed, but unsafe
unknown
unknown is the safer alternative to any. You can store any value in unknown, but you cannot use it without narrowing. This is ideal for API responses and untrusted external data.
let data: unknown = JSON.parse("{"id":1}");
data.id; // error: you must narrow first
void
void represents “no return value”. It is commonly used for functions that perform side effects such as logging, saving, or updating UI.
function log(message: string): void {
console.log(message);
}
never
never represents values that should never occur. It appears in functions that always throw errors or never finish, and it is useful for exhaustiveness checks in advanced code.
function fail(reason: string): never {
throw new Error(reason);
}
Arrays
Arrays are typed by specifying the element type. This prevents mixed-type collections and makes operations such as mapping and filtering safer.
let ids: number[] = [1, 2, 3];
ids.push(4); // OK
ids.push("5"); // Type error
Objects
Object types define the shape of data. This is critical for modeling real entities such as users, products, and API responses.
let user: { id: number; name: string } = {
id: 1,
name: "Yusuf"
};
user.name = "Elif"; // OK
user.name = 10; // Type error
Functions
Function types define input and output contracts. In production, typed functions are a major driver of maintainability, because they make refactoring safer and usage clearer across the codebase.
function add(a: number, b: number): number {
return a + b;
}
add(2, 3); // OK
add("2", 3); // Type error
Type aliases as a readability tool
Even with basic types, type aliases can make code clearer by giving meaning to common patterns. This is the first step toward “domain modeling”.
type UserId = number;
function getUser(id: UserId) {
// ...
}
Production guidance
- Prefer
unknownoveranyfor external data. - Keep strict null checks enabled and model nullable fields explicitly.
- Type function boundaries first (inputs/outputs), then refine internals.
- Use small type aliases to improve readability and intent.
What’s next
Basic types give you safety for individual variables and simple structures. Next, you will learn how TypeScript infers types automatically, and how to use inference to keep your code clean without losing correctness.