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

Make any[] the effective rest type when any is spread #50034

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34596,7 +34596,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
if (signatureHasRestParameter(signature)) {
const restType = getTypeOfSymbol(signature.parameters[signature.parameters.length - 1]);
if (!isTupleType(restType)) {
return restType;
return isTypeAny(restType) ? anyArrayType : restType;
}
if (restType.target.hasRestElement) {
return sliceTupleType(restType, restType.target.fixedLength);
Expand Down
8 changes: 4 additions & 4 deletions tests/baselines/reference/inferTypes1.types
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ type T18 = ReturnType<Function>; // Error
>T18 : any

type T19<T extends any[]> = ReturnType<(x: string, ...args: T) => T[]>; // T[]
>T19 : T[]
>T19 : T19<T>
>x : string
>args : T

Expand All @@ -121,12 +121,12 @@ type U15 = InstanceType<typeof Abstract>; // Abstract
>Abstract : typeof Abstract

type U16<T extends any[]> = InstanceType<new (x: string, ...args: T) => T[]>; // T[]
>U16 : T[]
>U16 : U16<T>
>x : string
>args : T

type U17<T extends any[]> = InstanceType<abstract new (x: string, ...args: T) => T[]>; // T[]
>U17 : T[]
>U17 : U17<T>
Copy link
Contributor Author

@Andarist Andarist Jul 25, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those 3 changes here are basically caused by the same issue.

Because target/source is now any[] and not any when we start comparing the signatures within the conditional type we don't pass the isTypeAssignable check here. Because of that the conditional type can't be "simplified" here to the trueType and thus the displayed type changed.

This check reaches the structuredTypeRelatedToWorker with types like:

source // any[]
target // [x: string, ...args: T]

I've expected this to be satisfied somewhere around this check but actually the target is not an array - it's a tuple and there is no logic supporting tuple targets here. The question is if this is deliberate or just an accidental omission?

I've played around with this more though and I've noticed 2 additional problems here though:

  1. any[] is not assignable to [string, ...any[]]. I understand why the error is reported for this case but in the presence of any in the type system it feels weird. Intuitively I've expected any[] to be assignable to all arrays and tuples, similarly to how anyFunctionType is always assignable, regardless of the parameters count etc, see the check here EDIT:// I know now that it's not how it's supposed to work, tuples might come with required elements and stuff and any[] doesn't guarantee that
  2. even if the previous point would get "fixed" then the base constraint for T here is unknown and not any[]. I don't understand why as I've expected the latter.

>x : string
>args : T

Expand Down Expand Up @@ -490,6 +490,6 @@ const result = invoker('test', true)({ test: (a: boolean) => 123 })
>123 : 123

type Foo2<A extends any[]> = ReturnType<(...args: A) => string>;
>Foo2 : string
>Foo2 : Foo2<A>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change is caused by pretty similar stuff to the one described here.

The only~ difference here is that we get:

source // any[]
target // A

and there is not a lot of logic related to handling type params in the structuredTypeRelatedToWorker. So this target stays as A, its constraint is not really requested - but, again, the constraint for some reason is unknown, instead of any[]. Even though T's declaration points to T extends any[].

>args : A