Hone logo
Hone
Problems

Record Type Helpers in TypeScript: Streamlining Data Manipulation

TypeScript's record types are powerful for defining objects with known keys and values. However, working with them can sometimes be verbose. This challenge asks you to create reusable helper functions that simplify common operations on record types, making your code cleaner and more maintainable.

Problem Description

You are tasked with creating three TypeScript functions that operate on record types. These functions will help you:

  1. pickProperties: Given a record type T and an array of keys K, return a new record type containing only the properties specified in K from T.
  2. omitProperties: Given a record type T and an array of keys K, return a new record type containing all properties from T except those specified in K.
  3. mergeRecords: Given two record types T1 and T2, return a new record type that merges the properties of both T1 and T2. If a key exists in both T1 and T2, the value from T2 should take precedence.

Key Requirements:

  • The functions must be type-safe, leveraging TypeScript's type system to ensure correctness.
  • The functions should handle cases where the input keys are not present in the record type gracefully (e.g., by simply omitting them or not including them in the merged record).
  • The functions should be generic, working with any record type.

Expected Behavior:

The functions should return a new record type, not modify the original. The resulting record type should accurately reflect the desired properties based on the input.

Edge Cases to Consider:

  • Empty key arrays for pickProperties and omitProperties.
  • Overlapping keys in mergeRecords.
  • Record types with optional properties.
  • Record types with union types as values.

Examples

Example 1: pickProperties

Input:
T = { a: string; b: number; c: boolean }
K = ['a', 'c']

Output:
{ a: string; c: boolean }

Explanation: The output record type contains only the 'a' and 'c' properties from the original record type T.

Example 2: omitProperties

Input:
T = { a: string; b: number; c: boolean }
K = ['b']

Output:
{ a: string; c: boolean }

Explanation: The output record type contains all properties from T except for the 'b' property.

Example 3: mergeRecords

Input:
T1 = { a: string; b: number }
T2 = { b: boolean; c: string }

Output:
{ a: string; b: boolean; c: string }

Explanation: The output record type contains all properties from both T1 and T2. The 'b' property from T2 (boolean) overwrites the 'b' property from T1 (number).

Example 4: Edge Case - Empty Key Array

Input:
T = { a: string; b: number }
K = []

Output:
{ a: string; b: number }

Explanation:  When the key array is empty, both `pickProperties` and `omitProperties` should return the original record type unchanged.

Constraints

  • All functions must be written in TypeScript.
  • The functions should be as type-safe as possible.
  • The functions should be relatively efficient (avoid unnecessary iterations or complex logic). Performance is not the primary concern, but avoid obviously inefficient solutions.
  • The input K array for pickProperties and omitProperties will always contain string values representing valid keys of the record type T.

Notes

  • Consider using TypeScript's utility types like Pick, Omit, and Merge as inspiration, but you are expected to implement the logic yourself.
  • Think about how to handle optional properties correctly.
  • Pay close attention to type inference and ensure your functions are correctly typed.
  • This challenge focuses on understanding and implementing type manipulations, not on complex data structures or algorithms. The core is working with TypeScript's type system.
Loading editor...
typescript