Hone logo
Hone
Problems

Type-Safe Includes with Custom Types in TypeScript

This challenge focuses on creating a utility type in TypeScript that mimics the functionality of the JavaScript includes() method, but with enhanced type safety. You'll define a type that accepts an array and a search value, and returns a boolean type indicating whether the array includes the value, while also ensuring type safety for both the array elements and the search value. This is useful for creating more robust and predictable code by leveraging TypeScript's type system.

Problem Description

You need to create a TypeScript type called Includes. This type should take two type arguments: T representing the type of elements in the array, and U representing the type of the value to search for. The Includes type should return a boolean type (true or false) based on whether an array of type T[] includes a value of type U.

Key Requirements:

  • Type Safety: The Includes type must ensure that the search value U is compatible with the array element type T. If they are not compatible, the type system should flag an error.
  • Boolean Result: The type should resolve to true if the array could include the value, and false otherwise. Note that this is a type-level check, not a runtime check. We are determining if the types are compatible, not actually searching the array.
  • Generic Types: The type must be generic, accepting the array element type and the search value type as parameters.

Expected Behavior:

The Includes type should be usable like this:

type ArrayType = [string, number, boolean];
type SearchValue = string;

type Result = Includes<ArrayType, SearchValue>; // Should be true

type Result2 = Includes<ArrayType, number>; // Should be false

type Result3 = Includes<[number, number], number>; // Should be true

Edge Cases to Consider:

  • Empty arrays: The type should still function correctly with empty arrays.
  • Arrays with mixed types (e.g., (string | number)[]): The type system should accurately reflect the potential types within the array.
  • never type: Consider how the type should behave if either T or U is never.

Examples

Example 1:

Input: ArrayType: [string, number, boolean], SearchValue: string
Output: true
Explanation: A string *could* be present in an array containing strings, numbers, and booleans.

Example 2:

Input: ArrayType: [string, number, boolean], SearchValue: number
Output: false
Explanation: A number is not guaranteed to be present in an array containing strings, numbers, and booleans.

Example 3:

Input: ArrayType: (string | number)[], SearchValue: string | number
Output: true
Explanation: A string or number *could* be present in an array containing strings or numbers.

Constraints

  • The solution must be a TypeScript type definition.
  • The solution should not use any runtime code (no functions or classes). It must be purely a type-level solution.
  • The solution should be as concise and readable as possible.

Notes

Think about how you can leverage conditional types and distributive conditional types to achieve the desired type-level inclusion check. Consider how to handle the case where the array type is a union of types. The goal is to determine if the search value could be present in the array, based on its type.

Loading editor...
typescript