Bird
Raised Fist0
Typescriptprogramming~20 mins

Mapped type for deep transformations in Typescript - Practice Problems & Coding Challenges

Choose your learning style10 modes available
Challenge - 5 Problems
🎖️
Deep Mapped Types Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
❓ Predict Output
intermediate
2:00remaining
Output of a deep readonly mapped type
What is the type of obj after applying the DeepReadonly mapped type to data?
Typescript
type DeepReadonly<T> = {
  readonly [K in keyof T]: T[K] extends object ? DeepReadonly<T[K]> : T[K]
};

const data = {
  name: "Alice",
  details: {
    age: 30,
    hobbies: ["reading", "hiking"]
  }
};

const obj: DeepReadonly<typeof data> = data;

// What happens if we try to assign obj.details.age = 31?
ATypeScript error: Property 'age' does not exist on type 'DeepReadonly<typeof data>'.
BRuntime error when assigning the value.
CTypeScript error: Cannot assign to 'age' because it is a read-only property.
DNo error, assignment works normally.
Attempts:
2 left
💡 Hint
Think about what 'readonly' means in TypeScript and how it applies recursively.
❓ Predict Output
intermediate
2:00remaining
Output of a deep partial mapped type
Given the DeepPartial type below, what is the type of partialUser?
Typescript
type DeepPartial<T> = {
  [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P]
};

interface User {
  id: number;
  profile: {
    name: string;
    address: {
      city: string;
      zip: string;
    };
  };
}

const partialUser: DeepPartial<User> = {
  profile: {
    address: {
      city: "New York"
    }
  }
};
ApartialUser can have any subset of User properties, including nested ones, all optional.
BpartialUser must have all properties of User defined.
CpartialUser can only omit top-level properties, nested properties are required.
DpartialUser cannot omit any properties; all are required.
Attempts:
2 left
💡 Hint
Look at how the optional modifier and recursion are applied in the mapped type.
🔧 Debug
advanced
2:00remaining
Identify the error in a deep required mapped type
The following DeepRequired type is intended to make all properties required recursively. Which option correctly identifies the error in the code?
Typescript
type DeepRequired<T> = {
  [P in keyof T]-?: T[P] extends object ? DeepRequired<T[P]> : T[P];
};
AIt only works on top-level properties, not nested ones.
BIt causes infinite recursion on types like arrays or functions because they are objects too.
CIt does not remove optional modifiers from properties.
DIt causes a syntax error due to missing semicolon.
Attempts:
2 left
💡 Hint
Consider what types extend object in TypeScript and how that affects recursion.
📝 Syntax
advanced
2:00remaining
Which mapped type syntax is correct for deep transformation?
Which option correctly defines a mapped type that recursively makes all properties readonly?
Atype DeepReadonly<T> = { readonly [K in keyof T]: T[K] extends object ? DeepReadonly<T[K]> : T[K] };
Btype DeepReadonly<T> = { [K in keyof T]: readonly DeepReadonly<T[K]> };
Ctype DeepReadonly<T> = { readonly [K in keyof T]: DeepReadonly<T[K]> };
Dtype DeepReadonly<T> = { [K in keyof T]: T[K] extends object ? readonly DeepReadonly<T[K]> : T[K] };
Attempts:
2 left
💡 Hint
Remember to check the placement of 'readonly' and the conditional type.
🚀 Application
expert
3:00remaining
Create a mapped type to deeply transform all string properties to number
Which option defines a mapped type DeepStringToNumber that recursively changes all string properties to number, leaving other types unchanged?
Atype DeepStringToNumber<T> = { [K in keyof T]: T[K] extends object ? DeepStringToNumber<T[K]> : number };
Btype DeepStringToNumber<T> = { [K in keyof T]: T[K] extends object ? DeepStringToNumber<T[K]> : T[K] extends string ? number : T[K] };
Ctype DeepStringToNumber<T> = { [K in keyof T]: T[K] extends string ? number : T[K] };
Dtype DeepStringToNumber<T> = { [K in keyof T]: T[K] extends string ? number : T[K] extends object ? DeepStringToNumber<T[K]> : T[K] };
Attempts:
2 left
💡 Hint
Check the order of conditional checks to handle strings before objects or vice versa.

Practice

(1/5)
1.

What is the main purpose of a mapped type in TypeScript?

easy
A. To create a new type by transforming each property of an existing type
B. To execute functions asynchronously
C. To define runtime values for variables
D. To handle errors in promises

Solution

  1. Step 1: Understand mapped types

    Mapped types create new types by applying transformations to each property of an existing type.
  2. Step 2: Compare options

    Only To create a new type by transforming each property of an existing type describes this behavior correctly; others relate to runtime or async concepts.
  3. Final Answer:

    To create a new type by transforming each property of an existing type -> Option A
  4. Quick Check:

    Mapped type = transform properties [OK]
Hint: Mapped types change keys' types one by one [OK]
Common Mistakes:
  • Confusing mapped types with runtime functions
  • Thinking mapped types handle async code
  • Mixing mapped types with error handling
2.

Which of the following is the correct syntax to define a simple mapped type that makes all properties of T optional?

type PartialType = ?
easy
A. type PartialType<T> = { [P in keyof T]: T[P] }
B. type PartialType<T> = { [P in keyof T]: Optional }
C. type PartialType<T> = { [P in keyof T]?: T[P] }
D. type PartialType<T> = { [P: string]: T }

Solution

  1. Step 1: Recall optional property syntax

    Adding a question mark after the property name makes it optional in mapped types.
  2. Step 2: Analyze options

    type PartialType<T> = { [P in keyof T]?: T[P] } uses ?: correctly to make properties optional. type PartialType<T> = { [P in keyof T]: T[P] } keeps properties required. type PartialType<T> = { [P: string]: T } uses string keys incorrectly. type PartialType<T> = { [P in keyof T]: Optional } uses a non-existent Optional type.
  3. Final Answer:

    type PartialType<T> = { [P in keyof T]?: T[P] } -> Option C
  4. Quick Check:

    Optional properties use ? after key [OK]
Hint: Use ? after [P in keyof T] to make properties optional [OK]
Common Mistakes:
  • Forgetting the ? to mark properties optional
  • Using string index instead of keyof T
  • Assuming Optional<T> is built-in
3.

Given the following code, what is the type of DeepReadonly<User>?

type DeepReadonly<T> = {
  readonly [P in keyof T]: T[P] extends object ? DeepReadonly<T[P]> : T[P]
};

interface User {
  name: string;
  address: {
    city: string;
    zip: number;
  };
}
medium
A. { name: string; readonly address: { readonly city: string; readonly zip: number; } }
B. { name: string; address: { city: string; zip: number; } }
C. { readonly name: string; address: { city: string; zip: number; } }
D. { readonly name: string; readonly address: { readonly city: string; readonly zip: number; } }

Solution

  1. Step 1: Understand DeepReadonly mapped type

    It recursively applies readonly to all properties, including nested objects.
  2. Step 2: Apply to User interface

    Both name and address become readonly, and inside address, city and zip are also readonly.
  3. Final Answer:

    { readonly name: string; readonly address: { readonly city: string; readonly zip: number; } } -> Option D
  4. Quick Check:

    DeepReadonly = recursive readonly [OK]
Hint: DeepReadonly adds readonly recursively to all nested properties [OK]
Common Mistakes:
  • Forgetting readonly on nested properties
  • Assuming only top-level properties are readonly
  • Confusing shallow and deep readonly
4.

Identify the error in this deep transformation mapped type:

type DeepPartial<T> = {
  [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
}
medium
A. Incorrect use of semicolon instead of comma in mapped type
B. No error; the type is correct
C. The conditional type should check for primitives, not objects
D. Missing semicolon after the mapped property

Solution

  1. Step 1: Check mapped type syntax

    TypeScript object types, including mapped types, accept both commas and semicolons as separators, including trailing ones.
  2. Step 2: Analyze the code

    The syntax is valid, and the logic correctly makes properties optional while recursing DeepPartial on nested objects and preserving primitives.
  3. Final Answer:

    No error; the type is correct -> Option B
  4. Quick Check:

    Mapped types accept , or ; [OK]
Hint: Mapped types support , or ; separators [OK]
Common Mistakes:
  • Thinking semicolons are invalid in mapped types
  • Confusing separator rules from object literals
  • Overlooking recursive conditional logic
5.

How would you write a mapped type DeepNonNullable<T> that recursively removes null and undefined from all properties of T, including nested objects?

hard
A. type DeepNonNullable<T> = { [P in keyof T]: T[P] extends object ? DeepNonNullable<NonNullable<T[P]>> : NonNullable<T[P]> }
B. type DeepNonNullable<T> = { [P in keyof T]: NonNullable<T[P]> }
C. type DeepNonNullable<T> = { [P in keyof T]: T[P] extends object ? NonNullable<DeepNonNullable<T[P]>> : T[P] }
D. type DeepNonNullable<T> = { [P in keyof T]: T[P] extends object ? DeepNonNullable<T[P]> : T[P] }

Solution

  1. Step 1: Understand NonNullable and recursion

    We must remove null and undefined from each property, then recurse if the property is an object.
  2. Step 2: Analyze options

    type DeepNonNullable<T> = { [P in keyof T]: T[P] extends object ? DeepNonNullable<NonNullable<T[P]>> : NonNullable<T[P]> } first applies NonNullable to the property, then recursively applies DeepNonNullable to the cleaned type. This ensures null/undefined are removed at every level.
  3. Final Answer:

    type DeepNonNullable<T> = { [P in keyof T]: T[P] extends object ? DeepNonNullable<NonNullable<T[P]>> : NonNullable<T[P]> } -> Option A
  4. Quick Check:

    Remove null then recurse for objects [OK]
Hint: Apply NonNullable before recursion for deep cleaning [OK]
Common Mistakes:
  • Not applying NonNullable before recursion
  • Recursing without removing null/undefined
  • Confusing order of conditional checks
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard