microsoft / microsoft/TypeScript

Difference in overload pick between JS and TS with default generic type parameter

Open
#39,509 1 comment 1 reaction 1 assignee View on GitHub

@sandersn is already working on this.

Since Jul 8, 2020.

Needs Investigation
Dominant language
Go
Stars
111k
Forks
14.3k
Avg merge
2d 4h
Merged PRs (30d)
132

Description

TypeScript Version: 4.0.0-dev.20200703, 3.9.2 (playground)

Search Terms: js ts overload difference, javascript different overload, javascript wrong overload, javascript overload generic empty object

Code
definition.d.ts

export class EmptyObjectOverloads<T = {}> {
    constructor(a: Readonly<T>);
    /** @deprecated */
    constructor(a: T, b?: any);
}

export class RecordOverloads<T = Record<string, any>> {
    constructor(a: Readonly<T>);
    /** @deprecated */
    constructor(a: T, b?: any);
}

ts-example.ts

import { EmptyObjectOverloads, RecordOverloads } from './declaration';

class TSExampleEmpty extends EmptyObjectOverloads {
    constructor(a: any) {
        // hover over super: constructor EmptyObjectOverloads<{}>(a: Readonly<{}>): EmptyObjectOverloads<{}> (+1 overload)
        super(a); 
    }
}

class TSExampleRecord extends RecordOverloads {
    constructor(a: any) {
        // hover over super: constructor RecordOverloads<Record<string, any>>(a: Readonly<Record<string, any>>): RecordOverloads<Record<string, any>> (+1 overload)
        super(a);
    }
}

js-example.js

class JSExampleEmpty extends EmptyObjectOverloads {
    /** @param {*} a */
    constructor(a) {
        // hover over super: constructor EmptyObjectOverloads<any>(a: any, b?: any): EmptyObjectOverloads<any> (+1 overload)
        super(a); // deprecation warning '(a: any, b?: any): EmptyObjectOverloads<any>' is deprecated ts(6385)
    }
}

class JSExampleRecord extends RecordOverloads {
    /** @param {*} a */
    constructor(a) {
        // hover over super: constructor RecordOverloads<Record<string, any>>(a: Readonly<Record<string, any>>): RecordOverloads<Record<string, any>> (+1 overload)
        super(a);
    }
}

Expected behavior:
Both TSExampleEmpty and JSExampleEmpty pick same overload similar to TSExampleRecord and JSExampleRecord.

Actual behavior:
TSExampleEmpty uses default generic value {} and picks first overload.
For JSExampleEmpty generic value to is any and second (deprecated) overload picked, while JSExampleRecord works as expected.

In real world examples this behavior marks all super(props); in React class components in JS files as deprecated.
Of course it's impossible to report TS issue without mentioning React 😆 related constructor declaration

Playground Link:
Example TS Example JS

Related Issues: Haven't found any

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.