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 StrategiesCore JSType SystemReact FundamentalsFunctionsMicrofrontendsGenericsAsync JSHooksObjectsMonorepoArrays'this' KeywordUtility TypesError HandlingModern JSBundle OptimizationPerformanceDOM & EventsState ManagementClasses & OOPCaching StrategiesComponent PatternsAuthenticationReact RouterFormsAdvanced PatternsFrontend SecurityConcurrent ReactServer ComponentsTestingEcosystemNetwork OptimizationCore Web VitalsBrowser APIs

Ready to practice Advanced Types?

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

Start Free Practice →