microsoft / TypeScript

TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
https://www.typescriptlang.org
Apache License 2.0
101.12k stars 12.5k forks source link

Instantiation expressions don't reject incompatible signatures in situations with mixed call and construct signatures #59319

Open Andarist opened 4 months ago

Andarist commented 4 months ago

🔎 Search Terms

instantiation expression signature applicable incompatible call construct class

🕗 Version & Regression Information

⏯ Playground Link

https://www.typescriptlang.org/play/?ts=5.6.0-dev.20240717#code/MYGwhgzhAEBiD29oG8C+BYAUFgLgTwAcBTaAFSIh2gF4UtpoAeU6IgDxyIDsATGLgK4BbAEZEATgD4AFGHEBzAFxkAlMtIBuetC5EA7kxbtOvGJXEBLLvJlylq5QnhbMqF1h5FQcksHhdKaE5KdQocFz8AqiscMC4cCzBOHhogsMYAIgzJFyA

💻 Code

class Foo {}

type Test = {
  <T extends number>(arg: T): T;
  new <T extends string>(arg: T): Foo;
};

declare const test: Test;
const intantiated = test<"">;

🙁 Actual behavior

An error gets reported:

Type 'string' does not satisfy the constraint 'number'.(2344)

And the final type of instantiated is computed as:

const intantiated: {
    <T extends number>(arg: T): T;
    new (arg: ""): Foo;
}

🙂 Expected behavior

I'm not 100% sure but it feels like this type could be successfully instantiated to { new (arg: ""): Foo; }. This is the only signature that matches the given type arguments.

Additional information about the issue

No response

Andarist commented 4 months ago

It just occurred to me... this is very related to https://github.com/microsoft/TypeScript/issues/51694 but currently it's not solved by https://github.com/microsoft/TypeScript/pull/51695

apendua commented 2 months ago

@Andarist

but currently it's not solved by https://github.com/microsoft/TypeScript/pull/51695

Have you tried rebasing it onto latest main? I tried something very similar to your PR on my end and it seems like it's also a valid fix for the issue described here.

Andarist commented 2 months ago

I can try later but this PR only limits the search within a "group" of signatures. Call and construct signatures are kept separately so it shouldn't change the behavior for this case here without some extra tweaks. IIRC I checked it when posting the comment above.

apendua commented 2 months ago

@Andarist Yeah that makes sense. But I think the reason you're seeing the error in the first place is because the first signature has a "number" type constraint so if it gets filtered out the error goes away.