Skip to content

Functioning NoInfer behavior in generic conditional typesΒ #57050

Closed as not planned
@craigphicks

Description

@craigphicks

πŸ” Search Terms

issue #14829
pull #56794 (The pull for 14829)

βœ… Viability Checklist

⭐ Suggestion

These are conditional type examples in the 2.8 release doc:

type Foo<T> = T extends { a: infer U; b: infer U } ? U : never;
type T10 = Foo<{ a: string; b: string }>; // string
type T11 = Foo<{ a: string; b: number }>; // string | number
type Bar<T> = T extends { a: (x: infer U) => void; b: (x: infer U) => void }
  ? U
  : never;
type T20 = Bar<{ a: (x: string) => void; b: (x: string) => void }>; // string
type T21 = Bar<{ a: (x: string) => void; b: (x: number) => void }>; // string & number

The proposal is that the such generic types support NoInfer, for example:

type Foo<T> = T extends { a: infer U; b: NoInfer<infer U> } ? U : never;
type T10 = Foo<{ a: string; b: string }>; // string
type T11 = Foo<{ a: string; b: number }>; // (expecting string)
type Bar<T> = T extends { a: (x: infer U) => void; b: (x: NoInfer< infer U>) => void }
  ? U
  : never;
type T20 = Bar<{ a: (x: string) => void; b: (x: string) => void }>; // string
type T21 = Bar<{ a: (x: string) => void; b: (x: number) => void }>; // (expecting string)

πŸ“ƒ Motivating Example

Testing the latest dev version with pull #56794, these results were obtained:

type Foo<T> = T extends { a: infer U; b: NoInfer<infer U> } ? U : never;
>Foo : Foo<T>
>a : U
>b : NoInfer<U>

type T10 = Foo<{ a: string; b: string }>; // string
>T10 : string
>a : string
>b : string

type T11 = Foo<{ a: string; b: number }>; // never (expecting string)
>T11 : never                     <- WAS EXPECTING STRING
>a : string
>b : number


type Bar<T> = T extends { a: (x: infer U) => void; b: (x: NoInfer< infer U>) => void }
>Bar : Bar<T>
>a : (x: infer U) => void
>x : U
>b : (x: NoInfer<infer U>) => void
>x : NoInfer<U>

  ? U
  : never;

type T20 = Bar<{ a: (x: string) => void; b: (x: string) => void }>; // string
>T20 : string
>a : (x: string) => void
>x : string
>b : (x: string) => void
>x : string

type T21 = Bar<{ a: (x: string) => void; b: (x: number) => void }>; // (expecting string)
>T21 : never                     <- WAS EXPECTING STRING
>a : (x: string) => void
>x : string
>b : (x: number) => void
>x : number

The location marked with <- WAS EXPECTING STRING show results of never where string was expected.

πŸ’» Use Cases

  1. What do you want to use this for?
    • generic type inference

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