Skip to content

[4.3, 4.4] Inline filtering mapped type conditional with infer fails #46020

Open
@phroggyy

Description

@phroggyy

Bug Report

As of TypeScript 4.3, when inlining a mapped type on the left-hand side of extends in a conditional type, TypeScript incorrectly evaluates the condition when the right-hand side contains another mapped type with infer and renders the false condition. When declaring the mapped type explicitly rather than inline, the ternary is correctly evaluated.

This is pretty hard to cover in words, so please check playground link for reproduction.

The language version can be changed to 4.2 to see it working correctly.

🔎 Search Terms

typescript infer inline mapped type never generic inference

🕗 Version & Regression Information

  • This changed between versions 4.2 and 4.3

⏯ Playground Link

Change TS language to 4.2 to see the code functioning correctly, and 4.3 or 4.4 to see failure.

Playground link with relevant code

💻 Code

type DefinedKeys<T> = {
  [K in keyof T]:
    string extends K ? never :
    number extends K ? never :
  K }

type KnownKeys<T> = DefinedKeys<T> extends {
    [_ in keyof T]: infer U
  }
  ? U
  : never;

// This type is the exact same as `KnownKeys`, but inlines `DefinedKeys<T>` instead of declaring it as a separate type
type FailingKnownKeys<T> = {
  [K in keyof T]:
    string extends K ? never :
    number extends K ? never :
  K } extends {
    [_ in keyof T]: infer U
  }
  ? U
  : never;

interface Flags {
  knownFlag1: boolean
  knownFlag2: boolean
  [x: string]: boolean | null | undefined;
}

type DefinedValidationKeys = DefinedKeys<Flags>
type KnownFlags = KnownKeys<Flags>
type FailingKnownFlags = FailingKnownKeys<Flags>

🙁 Actual behavior

In the above code sample, the type FailingKnownFlags is never (the false branch of the ternary of FailingKnownKeys<T>), while KnownFlags correctly is {knownFlag1: boolean, knownFlag2: boolean}

🙂 Expected behavior

KnownKeys<T> === FailingKnownKeys<T>

They are the same declaration, just one being inline and the other with an explicitly extracted type.

Metadata

Metadata

Assignees

Labels

BugA bug in TypeScriptNeeds InvestigationThis issue needs a team member to investigate its status.RescheduledThis issue was previously scheduled to an earlier milestone

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions