TypeScript Types Guide
A complete, example-driven reference for every TypeScript type concept — from primitives to advanced mapped and conditional types.
Contents
Primitive Types
TypeScript has 7 primitive types, matching JavaScript primitives plus two additional types for safety:
// JavaScript primitives
let name: string = "Alice";
let age: number = 30; // includes integers and floats
let active: boolean = true;
let nothing: null = null;
let undef: undefined = undefined;
let id: bigint = 9007199254740993n;
let sym: symbol = Symbol("id");
// TypeScript extras
let val: any = "anything"; // disables type checking (avoid when possible)
let input: unknown = getData(); // safer than any — must narrow before use
let never: never; // value that can never occur (exhaustive checks)
let empty: void = undefined; // function return type for no return valueInterface vs Type Alias
Both define object shapes. Key differences:
Interface
interface User {
id: number;
name: string;
email?: string; // optional
readonly role: string; // read-only
}
// Extending
interface Admin extends User {
permissions: string[];
}
// Declaration merging (unique to interface)
interface User {
createdAt: Date; // added to original User
}Type Alias
type User = {
id: number;
name: string;
email?: string;
};
// Intersection (equivalent to extends)
type Admin = User & { permissions: string[] };
// Can also represent non-objects:
type ID = string | number;
type Status = "active" | "inactive";
type Handler = (e: Event) => void;
type Maybe<T> = T | null | undefined;interface for object shapes and public APIs (extensible). Use type for unions, intersections, primitives, and computed types.Unions & Intersections
// Union — value can be one of several types
type ID = string | number;
type Status = "active" | "inactive" | "pending"; // literal union
// Discriminated union — each branch has a unique literal
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; side: number }
| { kind: "rectangle"; width: number; height: number };
function area(shape: Shape): number {
switch (shape.kind) {
case "circle": return Math.PI * shape.radius ** 2;
case "square": return shape.side ** 2;
case "rectangle": return shape.width * shape.height;
}
}
// Intersection — value must satisfy all types
type WithTimestamps = { createdAt: Date; updatedAt: Date };
type UserRecord = User & WithTimestamps;Generics
Generics allow writing reusable code that works over many types while maintaining type safety:
// Generic function
function first<T>(arr: T[]): T | undefined {
return arr[0];
}
const num = first([1, 2, 3]); // type: number | undefined
const str = first(["a", "b"]); // type: string | undefined
// Generic interface
interface ApiResponse<T> {
data: T;
status: number;
error?: string;
}
type UserResponse = ApiResponse<User>;
// Generic constraints
function getField<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
getField({ name: "Alice", age: 30 }, "name"); // ✓ string
getField({ name: "Alice" }, "missing"); // ✗ compile error
// Default type parameter
interface Container<T = string> {
value: T;
}
const c: Container = { value: "hello" }; // T defaults to stringUtility Types
TypeScript ships with built-in utility types that transform existing types:
interface User {
id: number;
name: string;
email: string;
password: string;
}
// Transform all fields
Partial<User> // all fields optional: { id?: number; name?: string; ... }
Required<User> // all fields required (removes ?)
Readonly<User> // all fields read-only
// Pick or remove fields
Pick<User, "id" | "name"> // { id: number; name: string }
Omit<User, "password"> // all fields except password
// Records and mappings
Record<string, User> // { [key: string]: User }
Record<"admin" | "user", User> // { admin: User; user: User }
// Set operations on union types
type ABC = "a" | "b" | "c";
Exclude<ABC, "a"> // "b" | "c"
Extract<ABC, "a" | "d"> // "a"
NonNullable<string | null | undefined> // string
// Function-related
ReturnType<typeof fetchUser> // infer return type
Parameters<typeof fetchUser> // infer parameter tuple
Awaited<Promise<User>> // UserType Narrowing
Narrowing refines a union type to a specific member inside a conditional block:
// typeof narrowing
function print(val: string | number) {
if (typeof val === "string") {
console.log(val.toUpperCase()); // string here
} else {
console.log(val.toFixed(2)); // number here
}
}
// instanceof narrowing
function handleError(err: Error | string) {
if (err instanceof Error) {
console.log(err.stack); // Error here
} else {
console.log(err); // string here
}
}
// 'in' narrowing
type Cat = { meow(): void };
type Dog = { bark(): void };
function speak(animal: Cat | Dog) {
if ("meow" in animal) {
animal.meow(); // Cat here
} else {
animal.bark(); // Dog here
}
}
// Custom type predicate
function isUser(val: unknown): val is User {
return (
typeof val === "object" &&
val !== null &&
"id" in val &&
"name" in val
);
}Advanced Types
// Mapped type — transform every key of a type
type Optional<T> = { [K in keyof T]?: T[K] };
type ReadOnly<T> = { readonly [K in keyof T]: T[K] };
// Conditional type
type IsArray<T> = T extends any[] ? true : false;
type IsArray_string = IsArray<string[]>; // true
type IsArray_number = IsArray<number>; // false
// Infer in conditional types
type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;
type Resolved = UnwrapPromise<Promise<User>>; // User
// Template literal types (TS 4.1+)
type EventName = "click" | "focus" | "blur";
type Handler = `on${Capitalize<EventName>}`;
// "onClick" | "onFocus" | "onBlur"
// Recursive types
type Json =
| string
| number
| boolean
| null
| Json[]
| { [key: string]: Json };Frequently Asked Questions
What is the difference between interface and type in TypeScript?
Both define object shapes. Interfaces support declaration merging and are extensible with extends. Type aliases are more flexible — they can represent unions, intersections, primitives, and computed types. Use interface for object shapes and public APIs; use type for unions and everything else.
What is 'unknown' vs 'any' in TypeScript?
'any' disables all type checking — you can call methods, access properties, and assign it anywhere without errors. 'unknown' is the safe alternative: you must narrow the type before using it. Prefer 'unknown' for values that could be anything.
What is a generic type in TypeScript?
A generic type accepts type parameters written as <T>. Generics let you write reusable, type-safe functions and interfaces that work across multiple types. For example, Array<T> is a generic representing an array of any type T.
What are union types in TypeScript?
A union type represents a value that can be one of several types, written with |. For example, string | number means the value can be either. Use type narrowing (typeof, instanceof, or in) to determine the specific type at runtime.
What are mapped types in TypeScript?
Mapped types create new types by transforming the properties of an existing type using the syntax { [K in keyof T]: ... }. Built-in utility types like Partial<T>, Required<T>, and Readonly<T> are all implemented as mapped types.
From the blog
View all →
May 13, 2026
Convert XML to JSON Online: Complete Guide for Developers (2026)

May 11, 2026
Convert CSV to JSON Online Free (Best Developer Guide 2026)

May 6, 2026
Convert YAML to JSON Online Free (2026 Developer Guide)

Apr 30, 2026
Convert JSON to Zod Schema Online (2026) – Free Tool & Complete Guide

Apr 30, 2026
Top 50 JavaScript to TypeScript Converters (2026) – Free, AI & Online Tools
Convert your JavaScript code to TypeScript automatically?
Use the JS to TS Converter →