Skip to content

Enum generic does not restrict union of possible objects where enum is defined #58634

Closed
@noahtallen

Description

@noahtallen

🔎 Search Terms

generic type does not get inferred, generic type is not restricted

🕗 Version & Regression Information

  • This is the behavior in every version I tried (5.5 beta, 5.x, 4.x, 3.x), and I reviewed the FAQ for entries about generic type inference

⏯ Playground Link

https://www.typescriptlang.org/play/?ts=5.4.5#code/KYOwrgtgBAyg9hYAVAFgSxAcwM5QN4BQUUA8iMFALxQDkc5NANEVEgO5xW0AuHTBAXwIEM3YACcAZgEMAxhQCC4zAFlpAB3wsA2vESoMOAHRlgAXQBc+AB5XwEAEYSBzYroTJ0WbEfZxL+ACeVtjc4oZCQiIgYlJyispIgerAADysUMDWYiAAJrh6noa4AHxaAJDcXphWSADcBOW50tzSVkqqGtpIZg1RAPT9UADCcOLiwLLcUNLKUNzJFGi4GJISE7lQAG5o0lAOcFVQHWqa0nnHiYsWBAsprMChHQBiY6ZcJ12FBt4m5L23RYPJ5Xe7UDpJFKpb7VHymEraGjNVo0AEEQasRa4WYUCahcJTYCbFASYB1KBobg0XDYYDACCGAA2gQpEHUcGw2DQDkZFG4nHU0k5M220kZYD5KBaUFycEeIBo0wgLVkKEumEhaRhxT+wBKRgIsnooSgkjgnGoeCqhis2t+pkYMpabRsVgAjAIBA1ZYVrVgAOqUlAAEWdAAozXAAJQNAiSMAgKZoegyuC+6qBqqh1qpJCZbKgfKwDw-HAlMNW6qO5HSATtUFpJAlKNaYhoSRQMN+zBUSjUO3GUwtwjEYhGkDYOC8oyMuCYMM1ozWGNQDEwFBwMCMzZOKB4sJoQmbfnq07ufSw3VmR0OMDTZYK7hGYszdSCiYxZkU6YASRgUHZTluV5eYBSFbEQCgOAHAAK0maY2BJCYoAAIm7FCZguFCaww2VHygZVuFVeYSSgccwjke9IIhRYAH4WEiAggA

💻 Code

Let's say you have an enum, and you create a map of those enums to another type. You want a function such that when you pass a specific enum, you must also pass the data associated with that enum.

I know this example is possible to achieve with discriminated unions, but the real-world code makes it a lot harder to use those. This example just demonstrates the problem in a small way:

enum SomeThings {
  One = 'one',
  Two = 'two',
}

interface ArgMap {
  [SomeThings.One]: {x: number},
  [SomeThings.Two]: {y: string}
}

interface ArgType< T extends SomeThings > {
  thing: T;
  data: ArgMap[T];
}

// It is not possible to call this with values that will actually cause an error.
function doSomethingWithData<T extends SomeThings>({thing, data}: ArgType<T>) {
  if (thing === SomeThings.One) {
    // Error: TS infers "data" as the union "{x: number} | {y: string}"
    // when it should be restricted to "ArgMap[T]", so "data.x" is not accessible
    console.log(data.x);
  }
}

🙁 Actual behavior

Typescript reports an error, because it thinks that data.x is a union of the possible data types. However, it should always be theoretically possible to restrict the type of data based on the enum associated with it. You can even use ArgType as expected by itself:

type TestData = ArgType<SomeThings.One>['data']; // correctly restricts to "{x: number}"

🙂 Expected behavior

As far as I can tell, the types are correct, because it is impossible to pass an ArgType<T> such that data does not match ArgMap[T]. So it should be possible to restrict the type here

Additional information about the issue

No response

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