Skip to content

Suggestion: Add a compiler flag to disallow mapping primitive types #21840

Closed
@ssonne

Description

@ssonne

With the upcoming conditional types in 21316, it will become possible to write mapped types that handle primitive types correctly. However, there's currently no support from the compiler to warn that a mapped type is being incorrectly applied to a primitive (see example below). I suggest two changes:

  1. Add a compiler flag that only allows a type that extends object to be used in a mapped type. A potential solution would be to disallow applying keyof to a primitive type.
  2. Rewrite commonly used mapped types such as Partial using conditional types, so that code applying them to primitives can compile using the new flag.

Example of how the current behavior of mapping primitive types to themselves (introduced in 12447) can go wrong:

type Lazy<T> = {
  [K in keyof T]: () => T[K];
};

type LazyContainer<T> = {
  val: Lazy<T>;
}

// This should definitely be an error, but it's not
const lazyContainer: LazyContainer<string> = { val: 'abc' };

function strictify<T>(x: Lazy<T>): T {
  const result: Partial<T> = {};

  for (const k in x) {
    result[k] = x[k]();
  }

  return result as T;
}

function strictifyContainer<T>(x: LazyContainer<T>): T {
  return strictify(x.val);
}

const strictString = strictifyContainer(lazyContainer); // runtime type error

With the new flag applied:

type Lazy<T> = {
  [K in keyof T]: () => T[K]; // error, T is not a subtype of object
};

Metadata

Metadata

Assignees

No one assigned

    Labels

    Working as IntendedThe behavior described is the intended behavior; this is not a bug

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions