Hone logo
Hone
Problems

Implementing Type Inference with infer in TypeScript

TypeScript's infer keyword allows you to extract types from within other types. This is a powerful feature for creating flexible and reusable type utilities. This challenge will guide you through implementing common type inference patterns.

Problem Description

Your task is to create a set of TypeScript type utilities that leverage the infer keyword to infer specific parts of existing types. You will need to build types that can extract:

  1. The element type of an array.
  2. The return type of a function.
  3. The type of the promise's resolved value.

These inferred types should be usable in various contexts, enabling more dynamic and type-safe code.

Examples

Example 1: Array Element Inference

// Type Utility to infer the element type of an array
type ElementType<T> = T extends (infer U)[] ? U : never;

// Usage
type MyArray = number[];
type Element = ElementType<MyArray>; // Expected: number

type AnotherArray = string[];
type AnotherElement = ElementType<AnotherArray>; // Expected: string

type NotAnArray = number;
type NonArrayElement = ElementType<NotAnArray>; // Expected: never

Example 2: Function Return Type Inference

// Type Utility to infer the return type of a function
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never;

// Usage
type MyFunction = () => string;
type Return = ReturnType<MyFunction>; // Expected: string

type AnotherFunction = (x: number, y: number) => number;
type AnotherReturn = ReturnType<AnotherFunction>; // Expected: number

type NotAFunction = string;
type NonFunctionReturn = ReturnType<NotAFunction>; // Expected: never

Example 3: Promise Resolved Value Inference

// Type Utility to infer the resolved value of a Promise
type PromiseResolvedValue<T> = T extends Promise<infer U> ? U : never;

// Usage
type MyPromise = Promise<number>;
type ResolvedValue = PromiseResolvedValue<MyPromise>; // Expected: number

type AnotherPromise = Promise<string[]>;
type AnotherResolvedValue = PromiseResolvedValue<AnotherPromise>; // Expected: string[]

type NotAPromise = number;
type NonPromiseResolvedValue = PromiseResolvedValue<NotAPromise>; // Expected: never

Constraints

  • Your solutions must be written in TypeScript.
  • You should define three distinct generic type aliases: ElementType, FunctionReturnType, and PromiseResolvedValue.
  • The type aliases should correctly infer the target types as demonstrated in the examples.
  • For inputs that do not match the expected pattern (e.g., providing a number to ElementType), the type should resolve to never.
  • Efficiency is not a primary concern, but the types should be clear and idiomatic TypeScript.

Notes

  • The infer keyword is used within conditional types (T extends ... ? ... : ...).
  • Think about how you can pattern-match the structure of arrays, functions, and Promises to extract the desired type.
  • Consider the use of any[] for the parameter types of functions to make the inference generic.
  • The never type is useful for cases where the inference cannot be applied.
Loading editor...
typescript