Skip to content

Allow nongeneric string mapping types to exist #47050

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

Merged
merged 9 commits into from
Jun 17, 2022

Conversation

weswigham
Copy link
Member

In the same way that `${number}` represents the set of all number strings, this lets Uppercase<string> represent the set of all strings unaffected by uppercasing (implying they're already uppercase), and the same for Lowercase, Capitalize, and Uncapitalize. As part of this, all of these string mapping types also are actually applied to template literal types, rather than... not. So Lowercase<`A${string}`> is now `a${Lowercase<string>}`, rather than the very clearly wrong `A${string}`. Capitalize and Uncapitalize only affect the first segment of a pattern template literal, reflecting their implementation, so Capitalize<`a${string}`> is just `A${string}`, while Capitalize<`${string}-${string}`> is `${Capitalize<string>}-${string}`.

Technically, this is a breaking change, since now Uppercase<string> isn't just string.

@weswigham weswigham requested a review from ahejlsberg December 7, 2021 02:16
@typescript-bot typescript-bot added Author: Team For Uncommitted Bug PR for untriaged, rejected, closed or missing bug labels Dec 7, 2021
@weswigham
Copy link
Member Author

@typescript-bot pack this

@typescript-bot
Copy link
Collaborator

typescript-bot commented Dec 8, 2021

Heya @weswigham, I've started to run the tarball bundle task on this PR at 361eaff. You can monitor the build here.

@typescript-bot
Copy link
Collaborator

typescript-bot commented Dec 8, 2021

Hey @weswigham, 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/116101/artifacts?artifactName=tgz&fileId=3CC3B629EB065F09C451C54A5B3D6000B74BC00C9B0848181C66C3F54A132E3C02&fileName=/typescript-4.6.0-insiders.20211208.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/[email protected]".;

@weswigham
Copy link
Member Author

cc @rbuckton this probably has fun interactions with #48094 - namely I think all these pattern-ish StringMapping types need special inference behavior just like bigint and number. Things like "string matches Lowercase<string> inference if it has a round-trippable .toLowerCase"

@weswigham weswigham added the Breaking Change Would introduce errors in existing code label Mar 23, 2022
@@ -19497,6 +19510,13 @@ namespace ts {
return Ternary.True;
}
}
else if (target.flags & TypeFlags.StringMapping) {
Copy link
Member

Choose a reason for hiding this comment

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

This check seems too broad.

@@ -22060,7 +22087,8 @@ namespace ts {
const value = (source as StringLiteralType).value;
return !!(target.flags & TypeFlags.Number && value !== "" && isFinite(+value) ||
target.flags & TypeFlags.BigInt && value !== "" && isValidBigIntString(value) ||
target.flags & (TypeFlags.BooleanLiteral | TypeFlags.Nullable) && value === (target as IntrinsicType).intrinsicName);
target.flags & (TypeFlags.BooleanLiteral | TypeFlags.Nullable) && value === (target as IntrinsicType).intrinsicName ||
target.flags & TypeFlags.StringMapping && isUnchangedByStringMapping(target.symbol, getStringLiteralType(value)));
Copy link
Member

Choose a reason for hiding this comment

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

Couldn't target be a string mapping over pretty much anything? That doesn't seem right.

@weswigham weswigham requested a review from ahejlsberg April 6, 2022 23:37
@jakebailey
Copy link
Member

Out of curiosity, how would something like Capitalize<`${string}${string}`> work? I think currently we collapse the two down into one template element.

@weswigham
Copy link
Member Author

Shouldn't make much difference; Capitalizing the combined hole or just the first hole of two is equivalent, behavior wise, and one of the two is canonical via construction, if that merging behavior exists, I think. Capitalize (and uncapitalize) are already smart enough to only apply to the first character/hole of the template.

>TU3 : Symbol(TU3, Decl(intrinsicTypes.ts, 1, 36))
>Uppercase : Symbol(Uppercase, Decl(lib.es5.d.ts, --, --))

type TU4 = Uppercase<any>; // any
type TU4 = Uppercase<any>; // Uppercase<`${any}`>
Copy link
Member

@rbuckton rbuckton Apr 7, 2022

Choose a reason for hiding this comment

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

Is there a reason we can't just produce Uppercase<any>? The choice to qualify it as `${any}` seems to be made here: https://github.com/microsoft/TypeScript/pull/47050/files#diff-d9ab6589e714c71e657f601cf30ff51dfc607fc98419bf72e04f6b0fa92cc4b8R15322

Copy link
Member Author

@weswigham weswigham Apr 8, 2022

Choose a reason for hiding this comment

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

Iirc, mostly just because, as written, nongeneric string mapping types can only exist over string, template literals, or other mappings (any open-ended stringy type) - it's a bit easier to work with and check for when the type set they're constructed with is smaller (by explicitly coercing anything else into a template type).

@weswigham
Copy link
Member Author

Since main is 4.8, @ahejlsberg, wanna update your reviews now?

@weswigham
Copy link
Member Author

Ping @ahejlsberg again~

@weswigham
Copy link
Member Author

@typescript-bot test this
@typescript-bot user test this
@typescript-bot run dt
@typescript-bot perf test this
@typescript-bot perf test this faster

@typescript-bot
Copy link
Collaborator

typescript-bot commented Jun 13, 2022

Heya @weswigham, I've started to run the extended test suite on this PR at ca66747. You can monitor the build here.

@typescript-bot
Copy link
Collaborator

typescript-bot commented Jun 13, 2022

Heya @weswigham, I've started to run the abridged perf test suite on this PR at ca66747. You can monitor the build here.

Update: The results are in!

@typescript-bot
Copy link
Collaborator

typescript-bot commented Jun 13, 2022

Heya @weswigham, I've started to run the parallelized Definitely Typed test suite on this PR at ca66747. You can monitor the build here.

@typescript-bot
Copy link
Collaborator

typescript-bot commented Jun 13, 2022

Heya @weswigham, I've started to run the diff-based user code test suite on this PR at ca66747. You can monitor the build here.

Update: The results are in!

@typescript-bot
Copy link
Collaborator

typescript-bot commented Jun 13, 2022

Heya @weswigham, I've started to run the perf test suite on this PR at ca66747. You can monitor the build here.

Update: The results are in!

@typescript-bot
Copy link
Collaborator

@weswigham
Great news! no new errors were found between main..refs/pull/47050/merge

@typescript-bot
Copy link
Collaborator

Heya @weswigham, I've run the RWC suite on this PR - assuming you're on the TS core team, you can view the resulting diff here.

@typescript-bot
Copy link
Collaborator

@weswigham
The results of the perf run you requested are in!

Here they are:

Comparison Report - main..47050

Metric main 47050 Delta Best Worst
Angular - node (v10.16.3, x64)
Memory used 357,941k (± 0.02%) 357,996k (± 0.02%) +55k (+ 0.02%) 357,777k 358,214k
Parse Time 2.10s (± 0.73%) 2.11s (± 0.66%) +0.01s (+ 0.72%) 2.09s 2.16s
Bind Time 0.89s (± 0.65%) 0.89s (± 0.53%) +0.00s (+ 0.34%) 0.88s 0.90s
Check Time 5.95s (± 0.33%) 5.94s (± 0.54%) -0.00s (- 0.05%) 5.86s 6.02s
Emit Time 6.09s (± 0.37%) 6.12s (± 0.72%) +0.02s (+ 0.38%) 6.04s 6.24s
Total Time 15.02s (± 0.24%) 15.06s (± 0.49%) +0.04s (+ 0.25%) 14.96s 15.25s
Compiler-Unions - node (v10.16.3, x64)
Memory used 206,406k (± 0.03%) 206,414k (± 0.03%) +8k (+ 0.00%) 206,282k 206,575k
Parse Time 0.84s (± 0.44%) 0.85s (± 0.52%) +0.01s (+ 0.83%) 0.84s 0.86s
Bind Time 0.53s (± 1.27%) 0.53s (± 1.37%) +0.01s (+ 0.95%) 0.52s 0.55s
Check Time 8.10s (± 0.48%) 8.16s (± 0.61%) +0.06s (+ 0.69%) 8.05s 8.29s
Emit Time 2.50s (± 0.70%) 2.52s (± 1.28%) +0.02s (+ 0.76%) 2.46s 2.60s
Total Time 11.98s (± 0.45%) 12.06s (± 0.49%) +0.08s (+ 0.68%) 11.95s 12.15s
Monaco - node (v10.16.3, x64)
Memory used 343,796k (± 0.02%) 343,746k (± 0.01%) -50k (- 0.01%) 343,673k 343,856k
Parse Time 1.61s (± 0.46%) 1.60s (± 0.72%) -0.00s (- 0.25%) 1.57s 1.62s
Bind Time 0.77s (± 1.01%) 0.77s (± 0.62%) -0.00s (- 0.26%) 0.76s 0.78s
Check Time 5.96s (± 0.49%) 5.98s (± 0.36%) +0.02s (+ 0.32%) 5.92s 6.02s
Emit Time 3.25s (± 0.65%) 3.25s (± 1.38%) +0.01s (+ 0.15%) 3.19s 3.39s
Total Time 11.58s (± 0.46%) 11.60s (± 0.39%) +0.02s (+ 0.16%) 11.52s 11.74s
TFS - node (v10.16.3, x64)
Memory used 305,109k (± 0.02%) 305,114k (± 0.01%) +5k (+ 0.00%) 305,030k 305,203k
Parse Time 1.30s (± 0.64%) 1.30s (± 0.56%) +0.00s (+ 0.23%) 1.28s 1.31s
Bind Time 0.72s (± 0.83%) 0.73s (± 0.96%) +0.00s (+ 0.55%) 0.72s 0.75s
Check Time 5.40s (± 0.51%) 5.38s (± 0.42%) -0.02s (- 0.32%) 5.31s 5.41s
Emit Time 3.40s (± 0.77%) 3.42s (± 1.30%) +0.02s (+ 0.53%) 3.35s 3.55s
Total Time 10.82s (± 0.25%) 10.83s (± 0.61%) +0.01s (+ 0.09%) 10.70s 11.01s
material-ui - node (v10.16.3, x64)
Memory used 469,122k (± 0.01%) 469,108k (± 0.01%) -14k (- 0.00%) 468,978k 469,201k
Parse Time 1.85s (± 0.67%) 1.85s (± 0.52%) -0.01s (- 0.38%) 1.83s 1.87s
Bind Time 0.69s (± 1.13%) 0.69s (± 1.34%) +0.00s (+ 0.44%) 0.67s 0.71s
Check Time 14.49s (± 0.94%) 14.37s (± 0.41%) -0.12s (- 0.85%) 14.28s 14.52s
Emit Time 0.00s (± 0.00%) 0.00s (± 0.00%) 0.00s ( NaN%) 0.00s 0.00s
Total Time 17.03s (± 0.84%) 16.91s (± 0.39%) -0.13s (- 0.75%) 16.81s 17.10s
xstate - node (v10.16.3, x64)
Memory used 580,560k (± 1.68%) 573,980k (± 0.02%) -6,581k (- 1.13%) 573,793k 574,224k
Parse Time 2.61s (± 0.31%) 2.63s (± 0.36%) +0.01s (+ 0.54%) 2.60s 2.65s
Bind Time 1.02s (± 0.61%) 1.02s (± 0.57%) +0.00s (+ 0.39%) 1.01s 1.03s
Check Time 1.54s (± 0.48%) 1.55s (± 0.64%) +0.01s (+ 0.65%) 1.54s 1.58s
Emit Time 0.07s (± 0.00%) 0.07s (± 0.00%) 0.00s ( 0.00%) 0.07s 0.07s
Total Time 5.24s (± 0.32%) 5.27s (± 0.32%) +0.02s (+ 0.44%) 5.24s 5.31s
Angular - node (v12.1.0, x64)
Memory used 335,614k (± 0.02%) 335,636k (± 0.03%) +23k (+ 0.01%) 335,497k 335,941k
Parse Time 2.08s (± 0.72%) 2.10s (± 0.47%) +0.01s (+ 0.62%) 2.08s 2.13s
Bind Time 0.85s (± 0.99%) 0.85s (± 0.58%) -0.01s (- 0.59%) 0.83s 0.85s
Check Time 5.78s (± 0.54%) 5.76s (± 0.40%) -0.01s (- 0.26%) 5.71s 5.80s
Emit Time 6.37s (± 0.80%) 6.39s (± 0.80%) +0.02s (+ 0.27%) 6.32s 6.55s
Total Time 15.08s (± 0.53%) 15.09s (± 0.42%) +0.01s (+ 0.07%) 14.98s 15.29s
Compiler-Unions - node (v12.1.0, x64)
Memory used 194,034k (± 0.10%) 193,984k (± 0.10%) -50k (- 0.03%) 193,249k 194,163k
Parse Time 0.84s (± 0.84%) 0.84s (± 1.00%) +0.00s (+ 0.24%) 0.83s 0.86s
Bind Time 0.55s (± 0.87%) 0.55s (± 0.87%) 0.00s ( 0.00%) 0.54s 0.56s
Check Time 7.54s (± 0.77%) 7.60s (± 0.42%) +0.06s (+ 0.78%) 7.52s 7.68s
Emit Time 2.53s (± 0.80%) 2.52s (± 1.24%) -0.01s (- 0.28%) 2.47s 2.60s
Total Time 11.46s (± 0.62%) 11.51s (± 0.39%) +0.05s (+ 0.45%) 11.39s 11.61s
Monaco - node (v12.1.0, x64)
Memory used 326,902k (± 0.02%) 326,838k (± 0.02%) -64k (- 0.02%) 326,697k 327,024k
Parse Time 1.57s (± 0.46%) 1.57s (± 0.73%) -0.00s (- 0.13%) 1.54s 1.59s
Bind Time 0.76s (± 0.66%) 0.75s (± 0.49%) -0.00s (- 0.00%) 0.75s 0.76s
Check Time 5.77s (± 0.43%) 5.78s (± 0.48%) +0.01s (+ 0.26%) 5.72s 5.86s
Emit Time 3.30s (± 0.92%) 3.30s (± 0.57%) -0.00s (- 0.03%) 3.26s 3.33s
Total Time 11.39s (± 0.28%) 11.41s (± 0.32%) +0.01s (+ 0.12%) 11.32s 11.50s
TFS - node (v12.1.0, x64)
Memory used 289,693k (± 0.02%) 289,652k (± 0.02%) -41k (- 0.01%) 289,529k 289,789k
Parse Time 1.30s (± 0.40%) 1.32s (± 0.88%) +0.02s (+ 1.31%) 1.28s 1.33s
Bind Time 0.75s (± 0.74%) 0.75s (± 0.63%) +0.00s (+ 0.67%) 0.74s 0.76s
Check Time 5.32s (± 0.66%) 5.33s (± 0.48%) +0.02s (+ 0.30%) 5.26s 5.37s
Emit Time 3.51s (± 0.51%) 3.54s (± 1.06%) +0.04s (+ 1.08%) 3.49s 3.65s
Total Time 10.87s (± 0.44%) 10.95s (± 0.53%) +0.08s (+ 0.70%) 10.79s 11.06s
material-ui - node (v12.1.0, x64)
Memory used 447,989k (± 0.06%) 448,197k (± 0.02%) +208k (+ 0.05%) 448,050k 448,436k
Parse Time 1.85s (± 0.60%) 1.84s (± 0.72%) -0.01s (- 0.49%) 1.83s 1.89s
Bind Time 0.68s (± 0.85%) 0.68s (± 0.59%) +0.00s (+ 0.15%) 0.67s 0.69s
Check Time 13.06s (± 0.64%) 12.95s (± 0.70%) -0.11s (- 0.84%) 12.79s 13.18s
Emit Time 0.00s (± 0.00%) 0.00s (± 0.00%) 0.00s ( NaN%) 0.00s 0.00s
Total Time 15.59s (± 0.53%) 15.47s (± 0.59%) -0.12s (- 0.76%) 15.30s 15.70s
xstate - node (v12.1.0, x64)
Memory used 539,653k (± 0.01%) 542,854k (± 1.33%) +3,201k (+ 0.59%) 539,353k 571,969k
Parse Time 2.57s (± 0.50%) 2.56s (± 0.59%) -0.01s (- 0.47%) 2.53s 2.59s
Bind Time 1.02s (± 1.17%) 1.00s (± 0.95%) -0.01s (- 1.38%) 0.99s 1.03s
Check Time 1.49s (± 0.55%) 1.49s (± 0.71%) -0.00s (- 0.00%) 1.47s 1.52s
Emit Time 0.07s (± 3.14%) 0.07s (± 4.13%) +0.00s (+ 1.41%) 0.07s 0.08s
Total Time 5.14s (± 0.47%) 5.13s (± 0.47%) -0.02s (- 0.35%) 5.08s 5.20s
Angular - node (v14.15.1, x64)
Memory used 333,823k (± 0.01%) 333,841k (± 0.01%) +18k (+ 0.01%) 333,763k 333,902k
Parse Time 2.07s (± 0.39%) 2.07s (± 0.45%) +0.00s (+ 0.14%) 2.06s 2.10s
Bind Time 0.89s (± 0.38%) 0.89s (± 0.91%) +0.01s (+ 0.68%) 0.88s 0.92s
Check Time 5.74s (± 0.34%) 5.74s (± 0.59%) 0.00s ( 0.00%) 5.67s 5.81s
Emit Time 6.39s (± 0.47%) 6.49s (± 2.00%) +0.11s (+ 1.69%) 6.31s 6.98s
Total Time 15.08s (± 0.33%) 15.20s (± 1.06%) +0.12s (+ 0.79%) 14.94s 15.77s
Compiler-Unions - node (v14.15.1, x64)
Memory used 192,844k (± 0.41%) 192,610k (± 0.02%) -233k (- 0.12%) 192,514k 192,679k
Parse Time 0.85s (± 0.87%) 0.85s (± 0.53%) -0.00s (- 0.24%) 0.84s 0.86s
Bind Time 0.58s (± 0.51%) 0.58s (± 0.99%) +0.00s (+ 0.35%) 0.57s 0.59s
Check Time 7.63s (± 0.57%) 7.65s (± 0.85%) +0.02s (+ 0.31%) 7.52s 7.77s
Emit Time 2.49s (± 0.60%) 2.51s (± 0.66%) +0.02s (+ 0.76%) 2.47s 2.54s
Total Time 11.55s (± 0.42%) 11.59s (± 0.62%) +0.04s (+ 0.36%) 11.43s 11.72s
Monaco - node (v14.15.1, x64)
Memory used 325,607k (± 0.01%) 325,636k (± 0.00%) +28k (+ 0.01%) 325,614k 325,675k
Parse Time 1.58s (± 0.68%) 1.59s (± 0.72%) +0.02s (+ 0.95%) 1.57s 1.62s
Bind Time 0.79s (± 1.33%) 0.79s (± 0.82%) -0.00s (- 0.25%) 0.77s 0.80s
Check Time 5.67s (± 0.36%) 5.67s (± 0.33%) -0.00s (- 0.07%) 5.63s 5.72s
Emit Time 3.36s (± 0.79%) 3.37s (± 0.67%) +0.01s (+ 0.30%) 3.31s 3.42s
Total Time 11.40s (± 0.18%) 11.41s (± 0.29%) +0.02s (+ 0.14%) 11.35s 11.50s
TFS - node (v14.15.1, x64)
Memory used 288,706k (± 0.01%) 288,731k (± 0.01%) +25k (+ 0.01%) 288,691k 288,790k
Parse Time 1.31s (± 0.88%) 1.33s (± 1.08%) +0.02s (+ 1.29%) 1.31s 1.37s
Bind Time 0.76s (± 0.29%) 0.76s (± 1.37%) -0.00s (- 0.39%) 0.74s 0.79s
Check Time 5.32s (± 0.45%) 5.31s (± 0.47%) -0.01s (- 0.15%) 5.24s 5.36s
Emit Time 3.51s (± 1.79%) 3.57s (± 1.90%) +0.06s (+ 1.77%) 3.46s 3.68s
Total Time 10.91s (± 0.52%) 10.98s (± 0.73%) +0.07s (+ 0.61%) 10.81s 11.11s
material-ui - node (v14.15.1, x64)
Memory used 446,405k (± 0.00%) 446,401k (± 0.01%) -4k (- 0.00%) 446,348k 446,442k
Parse Time 1.90s (± 0.53%) 1.90s (± 0.59%) +0.00s (+ 0.05%) 1.87s 1.92s
Bind Time 0.73s (± 0.96%) 0.73s (± 1.03%) -0.00s (- 0.27%) 0.71s 0.74s
Check Time 13.15s (± 0.76%) 13.13s (± 0.74%) -0.02s (- 0.15%) 13.00s 13.42s
Emit Time 0.00s (± 0.00%) 0.00s (± 0.00%) 0.00s ( NaN%) 0.00s 0.00s
Total Time 15.78s (± 0.63%) 15.76s (± 0.60%) -0.02s (- 0.12%) 15.59s 16.03s
xstate - node (v14.15.1, x64)
Memory used 537,363k (± 0.00%) 537,401k (± 0.00%) +38k (+ 0.01%) 537,361k 537,473k
Parse Time 2.59s (± 0.40%) 2.61s (± 0.53%) +0.02s (+ 0.70%) 2.58s 2.65s
Bind Time 1.15s (± 0.92%) 1.15s (± 1.09%) -0.01s (- 0.69%) 1.11s 1.17s
Check Time 1.52s (± 0.53%) 1.52s (± 0.45%) +0.01s (+ 0.40%) 1.51s 1.54s
Emit Time 0.07s (± 3.14%) 0.07s (± 3.14%) 0.00s ( 0.00%) 0.07s 0.08s
Total Time 5.34s (± 0.29%) 5.35s (± 0.32%) +0.02s (+ 0.30%) 5.33s 5.40s
System
Machine Namets-ci-ubuntu
Platformlinux 4.4.0-210-generic
Architecturex64
Available Memory16 GB
Available Memory1 GB
CPUs4 × Intel(R) Core(TM) i7-4770 CPU @ 3.40GHz
Hosts
  • node (v10.16.3, x64)
  • node (v12.1.0, x64)
  • node (v14.15.1, x64)
Scenarios
  • Angular - node (v10.16.3, x64)
  • Angular - node (v12.1.0, x64)
  • Angular - node (v14.15.1, x64)
  • Compiler-Unions - node (v10.16.3, x64)
  • Compiler-Unions - node (v12.1.0, x64)
  • Compiler-Unions - node (v14.15.1, x64)
  • Monaco - node (v10.16.3, x64)
  • Monaco - node (v12.1.0, x64)
  • Monaco - node (v14.15.1, x64)
  • TFS - node (v10.16.3, x64)
  • TFS - node (v12.1.0, x64)
  • TFS - node (v14.15.1, x64)
  • material-ui - node (v10.16.3, x64)
  • material-ui - node (v12.1.0, x64)
  • material-ui - node (v14.15.1, x64)
  • xstate - node (v10.16.3, x64)
  • xstate - node (v12.1.0, x64)
  • xstate - node (v14.15.1, x64)
Benchmark Name Iterations
Current 47050 10
Baseline main 10

Developer Information:

Download Benchmark

@typescript-bot
Copy link
Collaborator

@weswigham
The results of the perf run you requested are in!

Here they are:

Comparison Report - main..47050

Metric main 47050 Delta Best Worst
Angular - node (v14.15.1, x64)
Memory used 333,823k (± 0.01%) 333,856k (± 0.00%) +33k (+ 0.01%) 333,838k 333,889k
Parse Time 2.07s (± 0.39%) 2.08s (± 0.76%) +0.01s (+ 0.43%) 2.05s 2.12s
Bind Time 0.89s (± 0.38%) 0.89s (± 0.53%) +0.00s (+ 0.34%) 0.88s 0.90s
Check Time 5.74s (± 0.34%) 5.75s (± 0.24%) +0.01s (+ 0.10%) 5.72s 5.78s
Emit Time 6.39s (± 0.47%) 6.40s (± 0.66%) +0.02s (+ 0.30%) 6.34s 6.52s
Total Time 15.08s (± 0.33%) 15.12s (± 0.34%) +0.04s (+ 0.26%) 15.02s 15.25s
Compiler-Unions - node (v14.15.1, x64)
Memory used 192,844k (± 0.41%) 192,918k (± 0.37%) +74k (+ 0.04%) 192,504k 195,796k
Parse Time 0.85s (± 0.87%) 0.85s (± 0.40%) -0.00s (- 0.35%) 0.84s 0.85s
Bind Time 0.58s (± 0.51%) 0.58s (± 0.89%) +0.00s (+ 0.52%) 0.57s 0.59s
Check Time 7.63s (± 0.57%) 7.67s (± 0.65%) +0.04s (+ 0.48%) 7.51s 7.76s
Emit Time 2.49s (± 0.60%) 2.51s (± 0.95%) +0.01s (+ 0.60%) 2.46s 2.56s
Total Time 11.55s (± 0.42%) 11.60s (± 0.53%) +0.05s (+ 0.48%) 11.45s 11.75s
Monaco - node (v14.15.1, x64)
Memory used 325,607k (± 0.01%) 325,615k (± 0.00%) +8k (+ 0.00%) 325,587k 325,642k
Parse Time 1.58s (± 0.68%) 1.57s (± 0.51%) -0.00s (- 0.19%) 1.56s 1.59s
Bind Time 0.79s (± 1.33%) 0.79s (± 0.43%) -0.00s (- 0.38%) 0.78s 0.79s
Check Time 5.67s (± 0.36%) 5.68s (± 0.59%) +0.01s (+ 0.18%) 5.62s 5.76s
Emit Time 3.36s (± 0.79%) 3.36s (± 0.47%) +0.00s (+ 0.03%) 3.34s 3.39s
Total Time 11.40s (± 0.18%) 11.40s (± 0.44%) +0.00s (+ 0.03%) 11.33s 11.52s
TFS - node (v14.15.1, x64)
Memory used 288,706k (± 0.01%) 288,724k (± 0.01%) +18k (+ 0.01%) 288,646k 288,762k
Parse Time 1.31s (± 0.88%) 1.33s (± 1.18%) +0.02s (+ 1.22%) 1.31s 1.39s
Bind Time 0.76s (± 0.29%) 0.76s (± 0.92%) -0.00s (- 0.26%) 0.74s 0.77s
Check Time 5.32s (± 0.45%) 5.32s (± 0.25%) -0.00s (- 0.08%) 5.27s 5.34s
Emit Time 3.51s (± 1.79%) 3.50s (± 1.25%) -0.02s (- 0.48%) 3.45s 3.66s
Total Time 10.91s (± 0.52%) 10.90s (± 0.39%) -0.01s (- 0.07%) 10.86s 11.06s
material-ui - node (v14.15.1, x64)
Memory used 446,405k (± 0.00%) 446,301k (± 0.06%) -104k (- 0.02%) 445,259k 446,443k
Parse Time 1.90s (± 0.53%) 1.89s (± 0.48%) -0.00s (- 0.21%) 1.87s 1.91s
Bind Time 0.73s (± 0.96%) 0.73s (± 0.96%) +0.00s (+ 0.27%) 0.72s 0.75s
Check Time 13.15s (± 0.76%) 13.12s (± 0.83%) -0.03s (- 0.21%) 12.97s 13.39s
Emit Time 0.00s (± 0.00%) 0.00s (± 0.00%) 0.00s ( NaN%) 0.00s 0.00s
Total Time 15.78s (± 0.63%) 15.75s (± 0.70%) -0.03s (- 0.18%) 15.59s 16.01s
xstate - node (v14.15.1, x64)
Memory used 537,363k (± 0.00%) 537,398k (± 0.00%) +35k (+ 0.01%) 537,370k 537,449k
Parse Time 2.59s (± 0.40%) 2.60s (± 0.41%) +0.02s (+ 0.62%) 2.59s 2.63s
Bind Time 1.15s (± 0.92%) 1.15s (± 1.23%) -0.00s (- 0.35%) 1.11s 1.17s
Check Time 1.52s (± 0.53%) 1.53s (± 0.51%) +0.01s (+ 0.86%) 1.51s 1.55s
Emit Time 0.07s (± 3.14%) 0.07s (± 3.14%) 0.00s ( 0.00%) 0.07s 0.08s
Total Time 5.34s (± 0.29%) 5.36s (± 0.36%) +0.02s (+ 0.47%) 5.32s 5.40s
System
Machine Namets-ci-ubuntu
Platformlinux 4.4.0-210-generic
Architecturex64
Available Memory16 GB
Available Memory1 GB
CPUs4 × Intel(R) Core(TM) i7-4770 CPU @ 3.40GHz
Hosts
  • node (v14.15.1, x64)
Scenarios
  • Angular - node (v14.15.1, x64)
  • Compiler-Unions - node (v14.15.1, x64)
  • Monaco - node (v14.15.1, x64)
  • TFS - node (v14.15.1, x64)
  • material-ui - node (v14.15.1, x64)
  • xstate - node (v14.15.1, x64)
Benchmark Name Iterations
Current 47050 10
Baseline main 10

Developer Information:

Download Benchmark

Comment on lines +143 to +146
// you'd think these were equivalent - the outer `Uppercase` conceptually
// makes the inner `Lowercase` effectively a noop - but that's not so;
// the german sharp s makes that not completely true (lowercases to ss,
// which then uppercases to SS), so arbitrary nestings of mappings make differing sets!
Copy link
Member

Choose a reason for hiding this comment

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

Ugh.

But is it true that Uppercase<Lowercase<string>> is just Uppercase<string>?

Does last one wins apply, or is there something 'bout Turkish ı?

Copy link
Member Author

Choose a reason for hiding this comment

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

But is it true that Uppercase<Lowercase<string>> is just Uppercase<string>?

Nope.

Does last one wins apply,

Nope, differing mappings stack forever. Only, eg, Uppercase<Uppercase<...>> will collapse the multiple consecutive Uppercases.

is there something 'bout Turkish ı?

Yep.

"ı".toLowerCase().toUpperCase() !== "ı"

Copy link
Member

@DanielRosenwasser DanielRosenwasser Jun 16, 2022

Choose a reason for hiding this comment

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

I realized it while authoring, but I wanted it on the record (and I just wanted to comment with a rhyme).

Comment on lines 22183 to 22188
const mappingStack = [];
while (target.flags & TypeFlags.StringMapping) {
mappingStack.unshift(target.symbol);
target = (target as StringMappingType).type;
}
const mappedSource = reduceLeft(mappingStack, (memo, value) => getStringMappingType(value, memo), source);
Copy link
Member

Choose a reason for hiding this comment

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

You could just use push and reduceRight, no? I guess we might not define our own reduceRight.

Also, would be nice to have a comment. Consider:

Suggested change
const mappingStack = [];
while (target.flags & TypeFlags.StringMapping) {
mappingStack.unshift(target.symbol);
target = (target as StringMappingType).type;
}
const mappedSource = reduceLeft(mappingStack, (memo, value) => getStringMappingType(value, memo), source);
// We need to see whether applying the same mappings of the target
// onto the source would produce an identical type *and* that
// it's compatible with the inner-most non-string-mapped type.
//
// The intuition here is that if same mappings don't affect the source at all,
// and the source is compatible with the unmapped target, then they must
// still reside in the same domain.
const mappingStack = [];
while (target.flags & TypeFlags.StringMapping) {
mappingStack.push(target.symbol);
target = (target as StringMappingType).type;
}
const mappedSource = mappingStack.reduceRight((memo, value) => getStringMappingType(value, memo), source);

Copy link
Member

Choose a reason for hiding this comment

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

I agree, a comment like that would make it clearer what's going on.

Copy link
Member Author

Choose a reason for hiding this comment

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

You could just use push and reduceRight, no? I guess we might not define our own reduceRight.

Yep, that's the reason. We only have a reduceLeft and not a reduceRight utility function, and I usually prefer to use those if they're available (otherwise we should remove them right?). Given this array will likely never be more than a handful of elements long, my preference would be to keep the core helper in use, rather than use the (es6) array method. Less work for that one guy patching the TS compiler to run on a blackberry phone browser.

target = (target as StringMappingType).type;
}
const mappedSource = reduceLeft(mappingStack, (memo, value) => getStringMappingType(value, memo), source);
return mappedSource === source && isMemberOfStringMapping(source, target);
Copy link
Member

Choose a reason for hiding this comment

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

It's too bad that it's not clearer that target is modified, otherwise it looks at first glance like it'll result in runaway recursion.

type.flags & TypeFlags.StringLiteral ? getStringLiteralType(applyStringMapping(symbol, (type as StringLiteralType).value)) :
type.flags & TypeFlags.TemplateLiteral ? getTemplateLiteralType(...applyTemplateStringMapping(symbol, (type as TemplateLiteralType).texts, (type as TemplateLiteralType).types)) :
Copy link
Member

Choose a reason for hiding this comment

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

The fact that you have to spread the arguments in, ugh.

Copy link
Member

@DanielRosenwasser DanielRosenwasser left a comment

Choose a reason for hiding this comment

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

It took a bit of convincing myself in isMemberOfStringMapping but otherwise seems reasonable.

@weswigham weswigham merged commit 5c4caaf into microsoft:main Jun 17, 2022
@jcalz
Copy link
Contributor

jcalz commented Sep 15, 2022

This awesome feature was released with TS4.8 but wasn't mentioned in the release notes. I guess it flew in under the radar. I wonder if it could be added retroactively?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Author: Team Breaking Change Would introduce errors in existing code For Uncommitted Bug PR for untriaged, rejected, closed or missing bug
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

7 participants