Skip to content

Ensure rest type for source parameter is readonly in relations - #53258

Merged
Jake Bailey (jakebailey) merged 2 commits into
microsoft:mainfrom
jakebailey:fix-53255
Mar 20, 2023
Merged

Ensure rest type for source parameter is readonly in relations#53258
Jake Bailey (jakebailey) merged 2 commits into
microsoft:mainfrom
jakebailey:fix-53255

Conversation

@jakebailey

@jakebaileyJake Bailey (jakebailey) commented Mar 14, 2023

Copy link
Copy Markdown
Member

Fixes#53255
See also DefinitelyTyped/DefinitelyTyped#64739

Given:

declarefunctioneach<TextendsReadonlyArray<any>>(cases: ReadonlyArray<T>): (fn: (...args: T)=>any)=>void;constcases=[[1,'1'],[2,'2'],]asconst;consteacher=each(cases);// Error.eacher((a,b)=>{});// No error?eacher((...args)=>{const[a,b]=args;});

We used to say:

Argument of type '(a: 1 | 2, b: "1" | "2") => void' is not assignable to parameter of type '(...args: readonly [1, "1"] | readonly [2, "2"]) => any'.
Types of parameters 'a' and 'args' are incompatible.
Type 'readonly [1, "1"] | readonly [2, "2"]' is not assignable to type '[a: 1 | 2, b: "1" | "2"]'.
The type 'readonly [1, "1"]' is 'readonly' and cannot be assigned to the mutable type '[a: 1 | 2, b: "1" | "2"]'.(2345)

Here, the "source" type is [a: 1 | 2, b: "1" | "2"], but that can't be assigned to the target as the target is readonly. But, these are the rest arguments, so there's no way for this function to observe the read-only ness of the parameter. (Note: these are parameters, so directionality is swapped.)

I'm not sure if this is a perfect fix, but one way to "solve" this is to just ensure the tuple/array we cook up for the source is readonly, that way it's always compatible. This fixes the issue, but does change some error messages because they do observe the intermediary type here.

Maybe the "better" thing to do here would be to strip readonly-ness from both sourceType and targetType if they were produced via getRestTypeAtPosition? I haven't exactly found "the way" to do that yet, e.g. no helper named "remove readonly from tuple or array".

@jakebailey

Copy link
Copy Markdown
MemberAuthor

@typescript-bot

TypeScript Bot (typescript-bot) commented Mar 14, 2023

Copy link
Copy Markdown
Contributor

Heya Jake Bailey (@jakebailey), I've started to run the abridged perf test suite on this PR at 5f7155d. You can monitor the build here.

Update: The results are in!

@typescript-bot

TypeScript Bot (typescript-bot) commented Mar 14, 2023

Copy link
Copy Markdown
Contributor

Heya Jake Bailey (@jakebailey), I've started to run the diff-based top-repos suite on this PR at 5f7155d. You can monitor the build here.

Update: The results are in!

@typescript-bot

TypeScript Bot (typescript-bot) commented Mar 14, 2023

Copy link
Copy Markdown
Contributor

Heya Jake Bailey (@jakebailey), I've started to run the diff-based user code test suite on this PR at 5f7155d. You can monitor the build here.

Update: The results are in!

@typescript-bot

TypeScript Bot (typescript-bot) commented Mar 14, 2023

Copy link
Copy Markdown
Contributor

Heya Jake Bailey (@jakebailey), I've started to run the extended test suite on this PR at 5f7155d. You can monitor the build here.

@typescript-bot

TypeScript Bot (typescript-bot) commented Mar 14, 2023

Copy link
Copy Markdown
Contributor

Heya Jake Bailey (@jakebailey), I've started to run the parallelized Definitely Typed test suite on this PR at 5f7155d. You can monitor the build here.

Update: The results are in!

@typescript-bot

TypeScript Bot (typescript-bot) commented Mar 14, 2023

Copy link
Copy Markdown
Contributor

Heya Jake Bailey (@jakebailey), I've started to run the tarball bundle task on this PR at 5f7155d. You can monitor the build here.

@typescript-bot

TypeScript Bot (typescript-bot) commented Mar 14, 2023

Copy link
Copy Markdown
Contributor

Hey Jake Bailey (@jakebailey), I've packed this into an installable tgz. You can install it for testing by referencing it in your package.json like so:

{
"devDependencies": {
"typescript": "https://typescript.visualstudio.com/cf7ac146-d525-443c-b23c-0d58337efebc/_apis/build/builds/149439/artifacts?artifactName=tgz&fileId=E33B7102478AE1E2DBEF19B4743FF90C23816DB6BF2A8FC73E70ED7940D0E74302&fileName=/typescript-5.1.0-insiders.20230314.tgz"
}
}

and then running npm install.


There is also a playground for this build and an npm module you can use via "typescript": "npm:@typescript-deploys/pr-build@5.1.0-pr-53258-7".;

@typescript-bot

Copy link
Copy Markdown
Contributor

Jake Bailey (@jakebailey) Here are the results of running the user test suite comparing main and refs/pull/53258/merge:

Everything looks good!

@typescript-bot

Copy link
Copy Markdown
Contributor

Jake Bailey (@jakebailey)
The results of the perf run you requested are in!

Here they are:

Comparison Report - main..53258

Metricmain53258DeltaBestWorstp-value
Angular - node (v16.17.1, x64)
Memory used361,467k (± 0.01%)361,469k (± 0.01%)~361,424k361,494kp=0.687 n=6
Parse Time3.52s (± 0.30%)3.51s (± 0.46%)~3.49s3.53sp=0.250 n=6
Bind Time1.17s (± 1.17%)1.18s (± 0.54%)~1.17s1.19sp=0.654 n=6
Check Time9.48s (± 0.68%)9.44s (± 0.31%)~9.41s9.48sp=0.227 n=6
Emit Time7.96s (± 1.22%)7.93s (± 0.61%)~7.89s8.02sp=0.935 n=6
Total Time22.14s (± 0.58%)22.06s (± 0.22%)~21.99s22.12sp=0.296 n=6
Compiler-Unions - node (v16.17.1, x64)
Memory used194,247k (± 0.96%)192,516k (± 0.07%)~192,282k192,632kp=0.173 n=6
Parse Time1.58s (± 1.91%)1.57s (± 0.87%)~1.55s1.59sp=0.461 n=6
Bind Time0.82s (± 0.50%)0.82s (± 0.50%)~0.81s0.82sp=0.218 n=6
Check Time10.03s (± 0.70%)10.06s (± 0.36%)~10.02s10.12sp=0.421 n=6
Emit Time2.98s (± 0.60%)3.04s (± 4.15%)~2.98s3.30sp=0.142 n=6
Total Time15.41s (± 0.47%)15.49s (± 0.79%)+0.09s (+ 0.56%)15.43s15.74sp=0.043 n=6
Monaco - node (v16.17.1, x64)
Memory used346,711k (± 0.00%)346,721k (± 0.00%)~346,703k346,734kp=0.335 n=6
Parse Time2.72s (± 0.28%)2.73s (± 0.80%)~2.71s2.77sp=0.315 n=6
Bind Time1.09s (± 0.47%)1.08s (± 0.75%)~1.07s1.09sp=0.523 n=6
Check Time7.75s (± 0.70%)7.75s (± 0.28%)~7.71s7.77sp=0.870 n=6
Emit Time4.46s (± 1.21%)4.46s (± 0.90%)~4.42s4.53sp=0.871 n=6
Total Time16.02s (± 0.59%)16.03s (± 0.24%)~15.99s16.09sp=0.573 n=6
TFS - node (v16.17.1, x64)
Memory used300,127k (± 0.01%)300,140k (± 0.01%)~300,115k300,182kp=0.471 n=6
Parse Time2.16s (± 0.45%)2.16s (± 0.35%)~2.15s2.17sp=0.554 n=6
Bind Time1.24s (± 1.11%)1.24s (± 0.85%)~1.22s1.25sp=0.867 n=6
Check Time7.19s (± 0.44%)7.16s (± 0.65%)~7.10s7.22sp=0.261 n=6
Emit Time4.35s (± 0.36%)4.34s (± 0.70%)~4.30s4.38sp=0.568 n=6
Total Time14.94s (± 0.35%)14.89s (± 0.34%)~14.80s14.95sp=0.195 n=6
material-ui - node (v16.17.1, x64)
Memory used477,742k (± 0.01%)477,747k (± 0.00%)~477,718k477,776kp=0.575 n=6
Parse Time3.22s (± 0.17%)3.22s (± 0.47%)~3.19s3.23sp=0.498 n=6
Bind Time0.95s (± 1.10%)0.96s (± 0.54%)~0.95s0.96sp=0.794 n=6
Check Time18.06s (± 0.56%)18.19s (± 0.98%)~18.03s18.52sp=0.173 n=6
Emit Time0.00s (± 0.00%)0.00s (± 0.00%)~0.00s0.00sp=1.000 n=6
Total Time22.22s (± 0.49%)22.36s (± 0.81%)~22.20s22.71sp=0.128 n=6
xstate - node (v16.17.1, x64)
Memory used550,725k (± 0.02%)550,740k (± 0.02%)~550,631k550,935kp=1.000 n=6
Parse Time3.93s (± 0.37%)3.94s (± 0.25%)~3.92s3.95sp=0.624 n=6
Bind Time1.80s (± 0.65%)1.78s (± 0.46%)-0.01s (- 0.83%)1.77s1.79sp=0.048 n=6
Check Time3.04s (± 0.92%)3.02s (± 0.64%)~3.00s3.05sp=0.332 n=6
Emit Time0.09s (± 0.00%)0.09s (± 0.00%)~0.09s0.09sp=1.000 n=6
Total Time8.85s (± 0.35%)8.84s (± 0.39%)~8.80s8.88sp=0.571 n=6
System
Machine Namets-ci-ubuntu
Platformlinux 5.4.0-135-generic
Architecturex64
Available Memory16 GB
Available Memory15 GB
CPUs4 × Intel(R) Core(TM) i7-4770 CPU @ 3.40GHz
Hosts
  • node (v16.17.1, x64)
Scenarios
  • Angular - node (v16.17.1, x64)
  • Compiler-Unions - node (v16.17.1, x64)
  • Monaco - node (v16.17.1, x64)
  • TFS - node (v16.17.1, x64)
  • material-ui - node (v16.17.1, x64)
  • xstate - node (v16.17.1, x64)
BenchmarkNameIterations
Current532586
Baselinemain6

Developer Information:

Download Benchmark

@typescript-bot

Copy link
Copy Markdown
Contributor

Hey Jake Bailey (@jakebailey), it looks like the DT test run failed. Please check the log for more details.
You can check the log here.

@typescript-bot

Copy link
Copy Markdown
Contributor

Jake Bailey (@jakebailey) Here are the results of running the top-repos suite comparing main and refs/pull/53258/merge:

Everything looks good!

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Since this doesn't change applyToParameterTypes, this doesn't change inference, so won't be observable to a Parameters conditional call - you'll only see the difference in relationship error messages bewteen signatures. And maybe that's OK. It's s little weird to say that variadic rests are sometimes-readonly-sometimes-not, but... function parameters are pretty wonky on the edges as-is.

@jakebailey

Copy link
Copy Markdown
MemberAuthor

Yeah, this is just a case where inference is already right (the insides don't change).

Would my alternative suggestion of stripping readonly from rest types work better, if I can find the way to do that?

@jakebailey

Copy link
Copy Markdown
MemberAuthor

In general, I'm also having trouble seeing where anyone would ever want the result of Parameters to be readonly itself; it never matters what you pass into a function, the actual variadic parameters themselves are copied, so only individual parameters need to maintain readonly-ness (e.g. arrays).

@jakebailey

Jake Bailey (jakebailey) commented Mar 15, 2023

Copy link
Copy Markdown
MemberAuthor

Actually, I'm even more weirded out, because in my example above args is readonly [1, '1'] | readonly [2, '2'], but clearly mutating it will not mutate the input...

> const fn = (...args) => { args[0] = "oops" }
undefined
> const arr = ["some", "values"]
undefined
> fn(...arr)
undefined
> arr
[ 'some', 'values' ]

So, shouldn't we be stripping readonly in every case from rest arrays? That seems like the right fix...

@jakebailey
Jake Bailey (jakebailey) marked this pull request as draft March 15, 2023 23:21
@jakebailey

Copy link
Copy Markdown
MemberAuthor

I mean, maybe I guess this fix is okay just to get rid of the spurious relation error, and something that addresses my followup comments can come later?

@jakebailey
Jake Bailey (jakebailey) marked this pull request as ready for review March 15, 2023 23:28
@jakebailey

Copy link
Copy Markdown
MemberAuthor

@typescript-bot

TypeScript Bot (typescript-bot) commented Mar 15, 2023

Copy link
Copy Markdown
Contributor

Heya Jake Bailey (@jakebailey), I've started to run the parallelized Definitely Typed test suite on this PR at 5f7155d. You can monitor the build here.

Update: The results are in!

@typescript-bot

Copy link
Copy Markdown
Contributor

Hey Jake Bailey (@jakebailey), it looks like the DT test run failed. Please check the log for more details.
You can check the log here.

@weswigham

Copy link
Copy Markdown
Member

I mean, maybe I guess this fix is okay just to get rid of the spurious relation error, and something that addresses my followup comments can come later?

Seems reasonable.

@jakebailey

Copy link
Copy Markdown
MemberAuthor

Followup is here: #53398

@jakebailey
Jake Bailey (jakebailey) merged commit e9836a4 into microsoft:mainMar 20, 2023
@jakebailey
Jake Bailey (jakebailey) deleted the fix-53255 branch March 20, 2023 23:18
@sandersn

Nathan Shively-Sanders (sandersn) commented Mar 23, 2023

Copy link
Copy Markdown
Member

Breaks ckeditor__ckeditor5-upload on DT. Didn't notice it until today because the overnight tests were blocked by the --legacy-peer-deps problem.

Filed #53459 with a 5-line, 2-type repro.

@jakebailey

Copy link
Copy Markdown
MemberAuthor

My fault for not retrying DT until I saw the results...

@microsoftMicrosoft (microsoft) locked as resolved and limited conversation to collaborators Oct 22, 2025
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Author: TeamFor Milestone BugPRs that fix a bug with a specific milestone

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Parameters created from tuple are treated as mutable instead of immutable, unless written as "...args"

4 participants

@jakebailey@typescript-bot@weswigham@sandersn