正在加载,请稍候…

TypeScript Utility Types: Partial, Pick, Omit, Record, and More

A practical guide to TypeScript built-in utility types — Partial, Required, Pick, Omit, Record, Exclude, Extract, ReturnType, and when to use each one.

TypeScript Utility Types: The Practical Reference

TypeScript ships with a library of built-in utility types that transform existing types. Instead of duplicating type definitions, these let you derive new types from existing ones — reducing maintenance burden and keeping your codebase DRY.

Object Transformation Types

Partial<T>

Makes all properties optional.

interface User {
  id: number;
  name: string;
  email: string;
  role: 'admin' | 'user';
}

// All fields optional — useful for update payloads
type UserUpdate = Partial<User>;

function updateUser(id: number, changes: Partial<User>) {
  // changes can have any subset of User fields
}

updateUser(1, { name: 'Alice' });           // ✅
updateUser(1, { email: 'a@b.com', role: 'admin' });  // ✅

Required<T>

Makes all properties required (opposite of Partial).

interface Config {
  timeout?: number;
  retries?: number;
  baseUrl?: string;
}

// All fields required after initialization
type ResolvedConfig = Required<Config>;

function resolveConfig(input: Config): ResolvedConfig {
  return {
    timeout: input.timeout ?? 5000,
    retries: input.retries ?? 3,
    baseUrl: input.baseUrl ?? 'https://api.example.com',
  };
}

Readonly<T>

Makes all properties read-only (cannot be reassigned).

const config: Readonly<Config> = {
  timeout: 5000,
  retries: 3,
  baseUrl: 'https://api.example.com',
};

config.timeout = 1000;  // ❌ Error: Cannot assign to 'timeout' (read-only)

Pick<T, K>

Creates a type with only the selected keys.

interface User {
  id: number;
  name: string;
  email: string;
  passwordHash: string;
  createdAt: Date;
}

// Public-facing user — exclude sensitive fields
type PublicUser = Pick<User, 'id' | 'name' | 'email'>;

// Type: { id: number; name: string; email: string }

function getPublicProfile(user: User): PublicUser {
  return { id: user.id, name: user.name, email: user.email };
}

Omit<T, K>

Creates a type with the specified keys removed.

// Remove sensitive and auto-generated fields for creation input
type CreateUserInput = Omit<User, 'id' | 'passwordHash' | 'createdAt'>;

// Type: { name: string; email: string }

function createUser(input: CreateUserInput): User {
  return {
    ...input,
    id: generateId(),
    passwordHash: hashPassword(input.email),
    createdAt: new Date(),
  };
}

Pick vs Omit: Use Pick when you want a small subset of a large type. Use Omit when you want most of a type except a few fields.

Record<K, V>

Creates an object type with keys of type K and values of type V.

// Map from string keys to numbers
type ScoreMap = Record<string, number>;
const scores: ScoreMap = { alice: 95, bob: 87 };

// Map enum values to config objects
type EnvironmentConfig = Record<'dev' | 'staging' | 'prod', {
  apiUrl: string;
  debug: boolean;
}>;

const envConfig: EnvironmentConfig = {
  dev:     { apiUrl: 'http://localhost:3000', debug: true },
  staging: { apiUrl: 'https://staging.api.example.com', debug: true },
  prod:    { apiUrl: 'https://api.example.com', debug: false },
};

// More constrained: key must be a valid HTTP method
type HttpMethodHandlers = Record<'GET' | 'POST' | 'PUT' | 'DELETE', Function>;

Union/Intersection Type Helpers

Exclude<T, U>

Removes types from a union that are assignable to U.

type Status = 'pending' | 'active' | 'deleted' | 'banned';

// Remove administrative statuses
type UserFacingStatus = Exclude<Status, 'deleted' | 'banned'>;
// Type: 'pending' | 'active'

type NonNullableString = Exclude<string | null | undefined, null | undefined>;
// Type: string

Extract<T, U>

Keeps only types from a union that are assignable to U (opposite of Exclude).

type Events = 'click' | 'focus' | 'blur' | 'keydown' | 'keyup';

// Only keyboard events
type KeyboardEvents = Extract<Events, 'keydown' | 'keyup' | 'keypress'>;
// Type: 'keydown' | 'keyup'

// Extract object types from a union
type Shape = { kind: 'circle'; radius: number } | { kind: 'square'; side: number } | string;
type ShapeObject = Extract<Shape, object>;
// Type: { kind: 'circle'; radius: number } | { kind: 'square'; side: number }

NonNullable<T>

Removes null and undefined from a type.

type MaybeString = string | null | undefined;
type DefiniteString = NonNullable<MaybeString>;
// Type: string

function processName(name: string | null): string {
  const safe: NonNullable<typeof name> = name ?? 'Anonymous';
  return safe.toUpperCase();
}

Function-Related Types

ReturnType<T>

Extracts the return type of a function type.

function fetchUser(id: number) {
  return { id, name: 'Alice', email: 'alice@example.com' };
}

type FetchedUser = ReturnType<typeof fetchUser>;
// Type: { id: number; name: string; email: string }

// Works with async functions too
async function getConfig() {
  return { timeout: 5000, debug: false };
}

type Config = Awaited<ReturnType<typeof getConfig>>;
// Type: { timeout: number; debug: boolean }
// Note: Awaited unwraps the Promise

Parameters<T>

Extracts function parameters as a tuple type.

function createEvent(name: string, date: Date, attendees: number) {
  // ...
}

type CreateEventParams = Parameters<typeof createEvent>;
// Type: [name: string, date: Date, attendees: number]

// Useful for wrapper functions
function createEventWithLogging(...args: Parameters<typeof createEvent>) {
  console.log('Creating event:', args[0]);
  return createEvent(...args);
}

ConstructorParameters<T>

Extracts constructor parameters.

class HttpClient {
  constructor(baseUrl: string, timeout: number, headers: Record<string, string>) {}
}

type ClientConfig = ConstructorParameters<typeof HttpClient>;
// Type: [baseUrl: string, timeout: number, headers: Record<string, string>]

InstanceType<T>

Extracts the instance type of a constructor.

class ApiClient {
  get(url: string) { return fetch(url); }
  post(url: string, body: unknown) { return fetch(url, { method: 'POST' }); }
}

type Client = InstanceType<typeof ApiClient>;
// Type: ApiClient

// Useful with factory patterns
function createClient(): InstanceType<typeof ApiClient> {
  return new ApiClient();
}

Combining Utility Types

Real-world types often combine multiple utilities:

interface Article {
  id: string;
  title: string;
  content: string;
  authorId: string;
  publishedAt: Date;
  updatedAt: Date;
  tags: string[];
}

// Input for creating: no auto-generated fields
type CreateArticleInput = Omit<Article, 'id' | 'publishedAt' | 'updatedAt'>;

// Input for updating: all fields optional except id
type UpdateArticleInput = Partial<Omit<Article, 'id'>> & Pick<Article, 'id'>;

// Article preview: only display fields
type ArticlePreview = Pick<Article, 'id' | 'title' | 'authorId' | 'publishedAt' | 'tags'>;

// Deep partial (utility types don't go deep by default)
type DeepPartial<T> = {
  [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
};

Template Literal Types (Advanced)

// Generate event handler names from event names
type EventNames = 'click' | 'focus' | 'blur';
type HandlerNames = `on${Capitalize<EventNames>}`;
// Type: 'onClick' | 'onFocus' | 'onBlur'

// Generate getter/setter pairs
type Getters<T> = {
  [K in keyof T as `get${Capitalize<string & K>}`]: () => T[K];
};

interface User { name: string; age: number; }
type UserGetters = Getters<User>;
// Type: { getName: () => string; getAge: () => number }

Quick Reference

Utility Type What it does
Partial<T> All props optional
Required<T> All props required
Readonly<T> All props read-only
Pick<T, K> Keep only K keys
Omit<T, K> Remove K keys
Record<K, V> Object with K keys and V values
Exclude<T, U> Remove U from union T
Extract<T, U> Keep only U in union T
NonNullable<T> Remove null/undefined
ReturnType<T> Function return type
Parameters<T> Function parameter types
Awaited<T> Unwrap Promise type

→ View and explore complex JSON data structures with the JSON Viewer.