GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Infer operator returning container type instead of applied generic · Issue #48772 · microsoft/TypeScript

Infer operator returning container type instead of applied generic #48772

New issue
Copy link
New issue
Copy link
Closed
Closed
Infer operator returning container type instead of applied generic#48772
Copy link
Labels
Working as IntendedThe behavior described is the intended behavior; this is not a bugThe behavior described is the intended behavior; this is not a bug

Description

@kschat
Kyle Schattler (kschat)
opened on Apr 19, 2022
Issue body actions

Bug Report

🔎 Search Terms

infer, conditional type, generic, alias

🕗 Version & Regression Information

  • This changed between versions v4.1.5 and v4.2.3

⏯ Playground Link

Playground link with relevant code

💻 Code

type BaseContext<TConfig> = {
  foo: number;
  config: TConfig;
};

type FullContext<TConfig, TContext> = TContext & BaseContext<TConfig>;

type ExtractAdditionalContext<TContext extends FullContext<any, any>> =
  TContext extends FullContext<any, infer TAdditionalContext>
    ? TAdditionalContext
    : never;

type Config = Record<string, string>;
type AdditionalContext = { customValue: string };

type Context = FullContext<Config, AdditionalContext>;
type ExtractedAdditionalContext = ExtractAdditionalContext<Context>;

declare const additionalContext: AdditionalContext;
const test1: ExtractedAdditionalContext = additionalContext;

🙁 Actual behavior

I expected ExtractedAdditionalContext to be AdditionalContext or { customValue: string }, and for test1 to compile without error.

🙂 Expected behavior

ExtractedAdditionalContext is AdditionalContext & BaseContext<Config> which is the same type as Context. test1 results in a compiler error of:

Type 'AdditionalContext' is not assignable to type 'AdditionalContext & BaseContext<Config>'.
 Type 'AdditionalContext' is missing the following properties from type 'BaseContext<Config>': foo, config

Additional notes

When I remove the config property from BaseContext the issue is resolved.

Reacted by Max Coplan

Activity

  1. RyanCavanaugh commented on Apr 19, 2022

    @RyanCavanaugh
    Ryan Cavanaugh (RyanCavanaugh)
    on Apr 19, 2022
    Member
    More actions

    Bisected to #42284

  2. Ryan Cavanaugh (RyanCavanaugh)
    added
    Working as IntendedThe behavior described is the intended behavior; this is not a bugThe behavior described is the intended behavior; this is not a bug
    on Apr 19, 2022
  3. RyanCavanaugh commented on Apr 19, 2022

    @RyanCavanaugh
    Ryan Cavanaugh (RyanCavanaugh)
    on Apr 19, 2022
    Member
    More actions

    If you keep substituting in the expansions of each type and see the operation being performed, this is a correct inference -- as in many cases, there are multiple equally correct inferences that can be made, and as a result of the linked PR we switched from a certain correct inference to a different correct inference. In general it's not safe to assume that inferring onto a T & U will reliably "break apart" a source type which was also constructed through a T & U - this can happen, but is not guaranteed to.

  4. kschat commented on Apr 19, 2022

    @kschat
    Kyle Schattler (kschat)
    on Apr 19, 2022
    Author
    More actions

    Thanks for the quick reply! I can appreciate how this is a correct inference, but it's certainly surprising. I'm sure a case exists, but I'm having a hard time imaging a time where I'd want the current result.

    I guess it's partially surprising because I wrote FullContext<any, infer TAdditionalContext>, not infer TContext & BaseContext<any>. The syntax suggests that I'm asking the compiler to tell me what was provided to the second generic of the type. Clearly that's not how the infer keyword works, but that begs the question -- can we have that feature? :)

    Reacted by Max Coplan
  5. fatcerberus commented on Apr 20, 2022

    @fatcerberus
    Bruce Pascoe (fatcerberus)
    on Apr 20, 2022
    More actions

    The syntax suggests that I'm asking the compiler to tell me what was provided to the second generic of the type.

    Yeah, inference is structural, not nominal, so the type system is always working backwards from the output of the generic to figure out what should go in the infer position. It's a bit like solving for x in f(x, y) = z given fixed y and z - the solution isn't guaranteed to be unique, depending on what f does with its arguments.

    Clearly that's not how the infer keyword works, but that begs the question -- can we have that feature? :)

    I'm not a TypeScript team member, but from what I do know about how the type system works I'm going to say probably not - in many cases the compiler doesn't even know which type alias a type came from, so infer always has to be done structurally.

    Reacted by Ryan Cavanaugh and Kyle Schattler
  6. RyanCavanaugh commented on Apr 20, 2022

    @RyanCavanaugh
    Ryan Cavanaugh (RyanCavanaugh)
    on Apr 20, 2022
    Member
    More actions

    Nothing's impossible but in general we're not keen to spend time tweaking things in the grey areas of inference - there are always going to be cases where there's a structural inference going on here, so making 6 out of 10 cases work as opposed to 4 out of 10 cases doesn't really change the situation much.

  7. kschat commented on Apr 21, 2022

    @kschat
    Kyle Schattler (kschat)
    on Apr 21, 2022
    Author
    More actions

    Yeah, inference is structural, not nominal, so the type system is always working backwards from the output of the generic to figure out what should go in the infer position. It's a bit like solving for x in f(x, y) = z given fixed y and z - the solution isn't guaranteed to be unique, depending on what f does with its arguments.

    Thanks, I was missing this context and it explains why this is so difficult.

    Nothing's impossible but in general we're not keen to spend time tweaking things in the grey areas of inference

    That's reasonable and I understand why the team takes that position. I'll close this issue, thanks for you time.

    Reacted by Bruce Pascoe
  8. Kyle Schattler (kschat)
    closed this as completedon Apr 21, 2022
  9. kschat commented on Apr 21, 2022

    @kschat
    Kyle Schattler (kschat)
    on Apr 21, 2022
    Author
    More actions

    Dave Campion (@dpchamps) came up with a good solution to my problem that I'll post here for others. Instead of inferring the generic, we can omit the keys in BaseContext from FullContext. This can omit too much if AdditionalContext contains keys that are also in BaseContext, but that's not a problem in my case. Here's a working example.

    Reacted by Dave Campion
  10. microsoft
    locked as resolved and limited conversation to collaborators on Oct 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Working as IntendedThe behavior described is the intended behavior; this is not a bugThe 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

      You are visitor 01402503 — GeezerVison does not store the pages you look up.
      Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.