Skip to content

Broken inference for generic classes passed to a generic function taking an optional class #61633

Description

@LukeAbby

🔎 Search Terms

class inference, optional class, broken inference

🕗 Version & Regression Information

This changed in PR #31116

However, this was the first time that there was even a distinction between a generic and non-generic class during inference to my knowledge. This likely means this has existed ever since the ability to infer a generic class has existed.

⏯ Playground Link

https://www.typescriptlang.org/play/?#code/C4TwDgpgBAggdiAwgezgZ2AJwK4GNjKZQC8UcEA7lABQB09AhpgOZoBcUDCA2gLoCUJAHxRkAIwBWEfAG4AUHIBm2OPgCWqKACUIcACYRMAMQA2DVgFk1ADzVwAPACEGaCIjNo0UCNeC69XvBIqBg4+IRQAD5QKgaKdhB6JDH6EPHkekLUclC5UM6uAPwcBW4eaAA0coIA3gC+8nK45VAocMAMCZj2ACoi9Qo6qcZmljZ21G0dXfxyAPRzeUvLeQB6sCzYALa6wKKKUKCQUADkRxDIB1Od5JgnUGpecMh7LmhqzHAMYibQBFBgJgMHZ+IiXQ7gaAnWJpBJ6E60IA

💻 Code

type AnyConstructor = new (...args: any[]) => object;

function RenderFlagsMixin<BaseClass extends AnyConstructor | undefined = undefined>(
    Base?: BaseClass,
) {};

class Container<T> {}
//             ^ Only happens when the class is generic.

RenderFlagsMixin(Container)
//               ^ Argument of type 'typeof Container' is not assignable to parameter of type 'undefined'.

🙁 Actual behavior

BaseClass is inferred as undefined despite the call being the value Container.

🙂 Expected behavior

BaseClass should be inferred as typeof Container.

Additional information about the issue

No response

Activity

  1. jcalz commented on Apr 30, 2025

    @jcalz
    Contributor

    Oof, in TS5.5+, the following code crashes the compiler:

    function RenderFlagsMixin<T extends new (...args: any[]) => object>(Base?: T) { };
    class Container<T> { t?: T }
    RenderFlagsMixin(Container)

    Maybe this isn't 100% related to this bug report but just noting that I ran into this when trying to investigate.

  2. LukeAbby commented on Apr 30, 2025

    @LukeAbby
    Author

    More information on that crash:

    • It appears to require a minimum of "strictNullChecks": true in the tsconfig.
    • tsc when run alone will crash but tsc index.ts will not.
    • The commit with the regression is e1874f3.
    • It doesn't appear the t?: T is strictly necessary.
    • The traceback on 5.8.3 is:
    TypeError: Cannot read properties of undefined (reading '0')
        at getObjectTypeInstantiation (.data/TypeScript/lib/_tsc.js:62220:175)
        at instantiateTypeWorker (.data/TypeScript/lib/_tsc.js:62479:16)
        at instantiateTypeWithAlias (.data/TypeScript/lib/_tsc.js:62459:20)
        at instantiateType (.data/TypeScript/lib/_tsc.js:62437:29)
        at instantiateList (.data/TypeScript/lib/_tsc.js:62061:24)
        at instantiateTypes (.data/TypeScript/lib/_tsc.js:62075:12)
        at chooseOverload (.data/TypeScript/lib/_tsc.js:75485:39)
        at resolveCall (.data/TypeScript/lib/_tsc.js:75253:16)
        at resolveCallExpression (.data/TypeScript/lib/_tsc.js:75690:12)
        at resolveSignature (.data/TypeScript/lib/_tsc.js:76118:16)
    
  3. MartinJohns commented on Apr 30, 2025

    @MartinJohns
    Contributor
    • tsc when run alone will crash but tsc index.ts will not.

    When running tsc index.ts it won't use your local tsconfig, so strictNullChecks has the default value (false). Without this flag the type undefined doesn't exist anymore.

  4. Andarist commented on Apr 30, 2025

    @Andarist
    Contributor

    I put up a PR o fix this here: #61635
    when it comes to the crash, that is already addressed by already open #59972

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

Needs InvestigationThis issue needs a team member to investigate its status.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions