Skip to content

Can't infer from this type on static class method call in JS Doc #50952

Closed
@dead-claudia

Description

@dead-claudia

Bug Report

🔎 Search Terms

  • js inference
  • javascript inference

🕗 Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about differing type inference for JS and TS

💻 Code

JavaScript:

/** @template R */
export class Action {
    /**
     * @returns {R}
     */
    action() {
        throw new Error("This method is abstract!")
    }

    /**
     * @template {new () => Action<any>} C
     * @this {C}
     * @return {C extends new () => Action<infer T> ? T : never}
     */
    static run() {
        return new this().action()
    }
}

/** @extends {Action<number>} */
export class Foo extends Action {
    action() {
        return 1
    }
}

const handle = Foo.run()
Compiler Options
{
  "compilerOptions": {
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "strictPropertyInitialization": true,
    "strictBindCallApply": true,
    "noImplicitThis": true,
    "noImplicitReturns": true,
    "alwaysStrict": true,
    "esModuleInterop": true,
    "checkJs": true,
    "allowJs": true,
    "declaration": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "target": "ES2017",
    "jsx": "react",
    "module": "ESNext",
    "moduleResolution": "node"
  }
}

Playground Link: Provided

TypeScript:

export abstract class Action<R> {
    action(): R {
        throw new Error("This method is abstract!")
    }

    static run<C extends new () => Action<any>>(
        this: C,
    ): C extends new () => Action<infer T> ? T : never {
        return new this().action()
    }
}

export class Foo extends Action<number> {
    action() {
        return 1
    }
}

const handle = Foo.run()
Output
export class Action {
    action() {
        throw new Error("This method is abstract!");
    }
    static run() {
        return new this().action();
    }
}
export class Foo extends Action {
    action() {
        return 1;
    }
}
const handle = Foo.run();
Compiler Options
{
  "compilerOptions": {
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "strictPropertyInitialization": true,
    "strictBindCallApply": true,
    "noImplicitThis": true,
    "noImplicitReturns": true,
    "alwaysStrict": true,
    "esModuleInterop": true,
    "declaration": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "target": "ES2017",
    "jsx": "react",
    "module": "ESNext",
    "moduleResolution": "node"
  }
}

Playground Link: Provided

🙁 Actual behavior

The inferred type for handle to in the JS version is any, and the --noImplicitAny option is not respected.

🙂 Expected behavior

The inferred type for handle to be number for both, as the types are fully equivalent.

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugA bug in TypeScriptDomain: JSDocRelates to JSDoc parsing and type generationHelp WantedYou can do this

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions