Hone logo
Hone
Problems

Crafting Partial Type Helpers in TypeScript

TypeScript's type system is powerful, but sometimes you need to selectively update or modify existing types. This challenge focuses on creating utility types that generate "partial" versions of existing types, allowing you to specify which properties should be optional. This is incredibly useful for scenarios like updating user profiles where only a subset of fields might be provided.

Problem Description

You are tasked with creating two TypeScript utility types: Partialize and Requiredize.

  • Partialize<T>: This type should take a type T and return a new type where all properties of T are optional.
  • Requiredize<T>: This type should take a type T and return a new type where all properties of T are required (i.e., no longer optional). If the input type already has all properties required, the output should be identical to the input.

The goal is to demonstrate your understanding of conditional types and mapped types in TypeScript to achieve this selective type modification.

Key Requirements:

  • The solution must be type-safe.
  • The solution should handle primitive types correctly (e.g., string, number, boolean).
  • The solution should handle union types correctly.
  • The solution should handle intersection types correctly.
  • The solution should handle types with optional properties already.

Expected Behavior:

  • Partialize<MyType> should make all properties of MyType optional.
  • Requiredize<MyType> should make all properties of MyType required.
  • If MyType already has all properties required, Requiredize<MyType> should return MyType unchanged.

Edge Cases to Consider:

  • Empty object types ({})
  • Primitive types (e.g., string, number)
  • Types with already optional properties
  • Union and intersection types

Examples

Example 1:

type MyType = {
  name: string;
  age: number;
  email?: string;
};

// Expected Output:
// {
//   name?: string;
//   age?: number;
//   email?: string;
// }
type Partialized = Partialize<MyType>;

// Expected Output:
// {
//   name: string;
//   age: number;
//   email?: string;
// }
type Requiredized = Requiredize<MyType>;

Example 2:

type AlreadyRequired = {
  id: number;
  isActive: boolean;
};

// Expected Output:
// {
//   id: number;
//   isActive: boolean;
// }
type StillRequired = Requiredize<AlreadyRequired>;

// Expected Output:
// {
//   id?: number;
//   isActive?: boolean;
// }
type StillPartial = Partialize<AlreadyRequired>;

Example 3:

type PrimitiveType = string;

// Expected Output:
// string
type PartialPrimitive = Partialize<PrimitiveType>;

// Expected Output:
// string
type RequiredPrimitive = Requiredize<PrimitiveType>;

Constraints

  • The solution must be written in TypeScript.
  • The solution should be concise and readable.
  • The solution should not use any external libraries.
  • The solution should be type-safe and avoid any type errors.

Notes

  • Consider using mapped types and conditional types to achieve the desired behavior.
  • The ? operator is key to making properties optional.
  • Think about how to handle the case where a property is already optional or required.
  • Start with Partialize and then tackle Requiredize. Partialize is generally simpler.
  • Remember that TypeScript's type system is structural, not nominal. This means that types are compatible if they have the same structure, not necessarily the same name.
Loading editor...
typescript