Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using Parameters in a class member function gets incorrect result while all parameters are optional. #53541

Open
LvChengbin opened this issue Mar 27, 2023 · 3 comments · May be fixed by #53615
Labels
Bug A bug in TypeScript Help Wanted You can do this
Milestone

Comments

@LvChengbin
Copy link

Bug Report

🔎 Search Terms

🕗 Version & Regression Information

5.0.2 and 4.9.5

  • This is a crash
  • This changed between versions ______ and _______
  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about _________
  • I was unable to test this on prior versions because _______

⏯ Playground Link

https://www.typescriptlang.org/play?ts=5.0.2&ssl=15&ssc=1&pln=16&pc=1#code/FAYwNghgzlAEAqsDexZtgeg7AZgOwAoBKALlgDcB7ASwBMBuVdLXQ2PCAWwFMB+MqABcATtTwBzWKQo0GTNPgLsufASLHiANLCjcAHv3YBXTgCNuwqWSp1kAX2APgoSDFgBZADwANWPsHceLRw8AB8yPKwIJR4QsJGIIKUwkoADkamYNQgsJxkvkT2zuisSgB0FRDC4lBkAApVKgHCUD4A2gDk+B2wALrhhSglJYIAFtRQZZxlirAVZVU1UowlDk44RniJ1DGsAEzlldW1sA3CTRat8G2wXXg9-VIRJXjcAO4IxDNs84twRIw7EA

Playground link with relevant code

💻 Code

class T {
    // fn(): void;
    // fn( name?: string ): void;
    fn( name?: string, sex?: number ): void {}
}


class M<X extends T> {
    constructor( public m: X ) {}

    fn( ...args: Parameters<X['fn' ]> ) {
        this.m.fn( ...args );
    }
}

function fn2( ...args: Parameters<T[ 'fn' ]> ) {
    new T().fn( ...args );
}

🙁 Actual behavior

image

The fn method in class M has similar code with the global function fn2, but it get errors.

The error message disappears if I add function overload ( uncomment line 3 & 4 in playground ).

🙂 Expected behavior

@RyanCavanaugh RyanCavanaugh added Bug A bug in TypeScript Help Wanted You can do this labels Mar 28, 2023
@RyanCavanaugh RyanCavanaugh added this to the Backlog milestone Mar 28, 2023
@JoshuaKGoldberg
Copy link
Contributor

This isn't specific to class methods actually. It's that the tuple is based on a type parameter. A smaller repro that uses an interface & type without a class:

interface HasMethod {
    method(first?: string, second?: number): void;
}

function fn<HasMethodLike extends HasMethod>(
    instance: HasMethodLike,
    ...args: Parameters<HasMethodLike['method']>
) {
    instance.method(...args);
    //              ~~~~~~~
    // Argument of type 'string | number | undefined' is not assignable to parameter of type 'string | undefined'.
    //   Type 'number' is not assignable to type 'string'.

}

@Andarist
Copy link
Contributor

To fix this the compiler would have to create synthesized call arguments for spreadTypes with tuple constraints here:
https://github.dev/microsoft/TypeScript/blob/d105b6a9941b77b5d95f289733da26ec5b0fcff9/src/compiler/checker.ts#L32714-L32721

Based on this code, I thought that I would be able to also notice some issues around unions of tuples being spread even outside of generic contexts. However, so far, I can't find a case that would prove that. Even though those arguments are not synthesized in this case it still works OK thanks to other branches of the code in getSignatureApplicabilityError

@Andarist
Copy link
Contributor

Funny enough, it works with generic tuples:

interface HasMethod {
  method(name: string, sex?: number): void;
  method2(...args: [name: string, sex?: number] | [other: number]): void;
}

function fn<HasMethodLike extends HasMethod>(
  instance: HasMethodLike,
  ...args: Parameters<HasMethodLike["method"]>
) {
  instance.method(...args); // error
}

function fn2<HasMethodLike extends HasMethod>(
  instance: HasMethodLike,
  ...args: Parameters<HasMethodLike["method2"]>
) {
  instance.method2(...args); // OK
}

@LvChengbin LvChengbin changed the title Using Parameters in a class member function gets incorrect result while all parameters all optional. Using Parameters in a class member function gets incorrect result while all parameters are optional. Mar 29, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript Help Wanted You can do this
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants