Skip to content
SDETRole
SDETRole

TypeScript interview question

Which TypeScript utility types do you use most, and how do they help in test code?

beginner 0–2 yrs #utility-types#partial#omit#test-data

Short answer

Partial, Required, Pick, Omit, Record, Readonly, ReturnType and Awaited derive new types from existing ones, so test data builders, API payloads and config stay in sync with the source types. For example Omit<User, 'id'> for a create payload, or Partial<User> for builder overrides.

Answer

Utility types are built-in generic types that transform one type into another. Their value in test code is that test data, payloads and helpers derive from the real domain types, so when a developer adds or renames a field, the compiler points at every test that needs updating instead of the tests silently drifting.

The ones I use most

interface User {
  id: string;
  email: string;
  name: string;
  role: 'admin' | 'member';
  createdAt: string;
}

Partial / Required: make all properties optional or all required.

function buildUser(overrides: Partial<User> = {}): User {
  return {
    id: crypto.randomUUID(),
    email: `qa+${Date.now()}@example.com`,
    name: 'Test User',
    role: 'member',
    createdAt: new Date().toISOString(),
    ...overrides,
  };
}

const admin = buildUser({ role: 'admin' });

Omit / Pick: remove or select properties. A create payload has no server-generated fields:

type CreateUserPayload = Omit<User, 'id' | 'createdAt'>;
type UserSummary = Pick<User, 'id' | 'email'>;

Record: an object type with known keys and a value type. Combined with a union it guarantees every key is present:

type Env = 'dev' | 'staging' | 'prod';
const baseUrls: Record<Env, string> = {
  dev: 'http://localhost:3000',
  staging: 'https://staging.example.com',
  prod: 'https://example.com',
}; // forgetting 'prod' is a compile error

Readonly: prevent tests from mutating shared fixtures (shallow).

const DEFAULT_USER: Readonly<User> = buildUser();
// DEFAULT_USER.role = 'admin'; // error

ReturnType, Parameters, Awaited: derive types from functions you do not control or do not want to duplicate.

async function login(email: string, password: string) {
  return { token: 'abc', expiresIn: 3600 };
}

type LoginArgs = Parameters<typeof login>;            // [email: string, password: string]
type Session = Awaited<ReturnType<typeof login>>;     // { token: string; expiresIn: number }

Also worth knowing

  • NonNullable<T> removes null and undefined.
  • Extract<T, U> and Exclude<T, U> filter union members: Exclude<User['role'], 'admin'> is 'member'.
  • satisfies (TypeScript 4.9+) is not a utility type but pairs well with them: it checks a value against a type while keeping the narrower inferred type.
const timeouts = { short: 2_000, long: 30_000 } satisfies Record<string, number>;
timeouts.short; // type number, and the key 'short' is known

What interviewers look for

  • Several utility types with correct semantics, not just names.
  • Realistic test-code uses: builders with Partial, payloads with Omit, config with Record.
  • The reason they matter: types derived from a single source of truth.
  • Awareness that Readonly and Partial are shallow.

A strong answer covers

  • Partial and Required change optionality
  • Pick and Omit select or remove properties
  • Record for maps keyed by a union
  • ReturnType, Parameters, Awaited for deriving from functions
  • Explains the benefit: derived types stay in sync with the source
Practise answering under time pressure

Type to search across SDETRole.

Full-text search by Pagefind · runs in your browser Open search page →