Typescript · Advanced Types

Advanced Types Interview Questions
With Answers & Code Examples

3 carefully curated Advanced Types interview questions with working code examples and real interview gotchas.

Practice Interactively →← All Categories
3 questions0 beginner0 core3 advanced
Q1Advanced

What are mapped types and how do you use them beyond the built-in utility types?

💡 Hint: [K in keyof T] iterates over type keys — combine with as to remap keys, conditional types to filter, modifiers to change optionality

Mapped types transform existing types by iterating over their keys and applying transformations to each property.

// Basic structure
type Mapped<T> = {
  [K in keyof T]: TransformedType;
};

// Value transformation — wrap each value in a Box
type Boxed<T> = {
  [K in keyof T]: { value: T[K] };
};

type BoxedUser = Boxed<User>;
// { id: { value: number }; name: { value: string }; ... }

Key remapping with as:

// Add prefix to all keys
type Prefixed<T, P extends string> = {
  [K in keyof T as `${P}_${string & K}`]: T[K];
};

type PrefixedUser = Prefixed<User, 'user'>;
// { user_id: number; user_name: string; ... }

// Convert to setters
type Setters<T> = {
  [K in keyof T as `set${Capitalize<string & K>}`]: (value: T[K]) => void;
};

Filtering keys with conditional + never:

// Keep only method keys
type MethodKeys<T> = {
  [K in keyof T]: T[K] extends Function ? K : never;
}[keyof T];

// Keep only string-valued properties
type StringProps<T> = {
  [K in keyof T as T[K] extends string ? K : never]: T[K];
};

// Flatten optional — convert T | undefined to T
type NonOptional<T> = {
  [K in keyof T]-?: Exclude<T[K], undefined>;
};
💡 The pattern [K in keyof T as CondType extends never ? never : K] is how TypeScript's built-in Omit and conditional key removal work. Mastering key remapping with as unlocks very powerful type transformations.
Practice this question →
Q2Advanced

What are conditional types and how do you use infer for type extraction?

💡 Hint: T extends U ? X : Y — use infer inside extends to capture and name a type for use in X or Y

Conditional types are TypeScript's equivalent of if-else for types. Combined with infer, they let you extract type information from complex types.

// Unwrap a Promise
type Awaited<T> = T extends Promise<infer U> ? Awaited<U> : T;
// If T is a Promise, extract what it resolves to and recurse
// Otherwise return T as-is

// Extract the element type of an array
type ArrayElement<T> = T extends (infer E)[] ? E : never;
type Elem = ArrayElement<string[]>; // string

// Extract return type
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never;

// Extract the first parameter
type FirstParam<T> = T extends (first: infer F, ...rest: any[]) => any
  ? F
  : never;

type FP = FirstParam<(a: string, b: number) => void>; // string

Multiple infer in one conditional:

// Extract both key and value types from a Map
type MapTypes<T> = T extends Map<infer K, infer V>
  ? { key: K; value: V }
  : never;

type UserMap = MapTypes<Map<string, User>>;
// { key: string; value: User }

// Flatten one level of nesting
type Flatten<T> = T extends Array<infer E>
  ? E extends Array<infer Inner> ? Inner : E
  : T;

type Flat = Flatten<number[][]>; // number[]
💡 infer only works inside extends clauses of conditional types. Think of it as "if this type matches this pattern, capture the matched part as a new type variable".
Practice this question →
Q3Advanced

What are template literal types in TypeScript?

💡 Hint: Type-level string interpolation — `${"Type"}` creates new string literal types from existing ones

Template literal types extend string literal types using template literal syntax to create new string types programmatically.

// Basic template literal type
type Greeting = `Hello, ${string}!`;
// Matches any string like "Hello, World!" "Hello, Alice!" etc.

type EventName = 'click' | 'focus' | 'blur';
type HandlerName = `on${Capitalize<EventName>}`;
// 'onClick' | 'onFocus' | 'onBlur'

// Distribution — template distributes over union members
type CSSProperty = 'margin' | 'padding';
type CSSDirectional = `${CSSProperty}-${'top' | 'right' | 'bottom' | 'left'}`;
// 'margin-top' | 'margin-right' | ... | 'padding-left' (8 combinations)

Practical patterns:

// Event emitter type-safe API
type EventMap = { 'user:login': User; 'user:logout': void; 'data:update': Data };

type EventEmitter = {
  on<K extends keyof EventMap>(event: K, handler: (data: EventMap[K]) => void): void;
  emit<K extends keyof EventMap>(...args: EventMap[K] extends void ? [K] : [K, EventMap[K]]): void;
};

// Building getter/setter pairs
type Accessors<T> = {
  [K in keyof T as `get${Capitalize<string & K>}`]: () => T[K];
} & {
  [K in keyof T as `set${Capitalize<string & K>}`]: (val: T[K]) => void;
};

// Route param extraction
type RouteParams<T extends string> =
  T extends `${infer _Start}:${infer Param}/${infer Rest}`
    ? Param | RouteParams<`/${Rest}`>
    : T extends `${infer _Start}:${infer Param}`
    ? Param
    : never;

type Params = RouteParams<'/users/:id/posts/:postId'>;
// 'id' | 'postId'
💡 Template literal types + mapped types + infer can parse and transform string types at compile time. This powers popular libraries like tRPC and Prisma to provide end-to-end type safety from strings.
Practice this question →

Other Typescript Interview Topics

Rendering Strategies →Core JS →Type System →React Fundamentals →Functions →Microfrontends →Generics →Async JS →Hooks →Objects →Monorepo →Arrays →'this' Keyword →Utility Types →Error Handling →Modern JS →Bundle Optimization →Performance →DOM & Events →State Management →Classes & OOP →Caching Strategies →Component Patterns →Authentication →React Router →Forms →Advanced Patterns →Frontend Security →Concurrent React →Server Components →Testing →Ecosystem →Network Optimization →Core Web Vitals →Browser APIs →

Ready to practice Advanced Types?

Get AI feedback on your answers, predict code output, and fix real bugs.

Start Free Practice →