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

Improve narrowing of generic types in control flow analysis #43183

Merged
merged 15 commits into from
Mar 20, 2021
Merged

Conversation

ahejlsberg
Copy link
Member

@ahejlsberg ahejlsberg commented Mar 10, 2021

In #15576 we improved control flow analysis for references of generic types with nullable constraints when those references occur in constraint positions (locations where it is known we'll fetch the constraint).

This PR expands the concept further. Specifically, when the type of a reference is or contains a generic type with a union type constraint, and when the reference is in a constraint position or has a contextual type containing no generic types (meaning constraints will determine assignability), we substitute constraints for all generic types in the type of the reference to give control flow analysis an opportunity to narrow it further. For example:

function f1<T extends string | undefined>(x: T): string {
    if (x) {
        x.length;  // x narrowed to string
        return x;  // x narrowed to string (error before this PR)
    }
}

Above, in x.length we substitute string | undefined for T in the type of x because x occurs in a constraint position. Similarly in return x we substitute string | undefined for T in the type of x because x has the contextual type string (due to the return type annotation on the containing function) which contains no generic types. Following substitution, control flow analysis is then able to narrow string | undefined to string based on the truthiness check in the containing if statement.

Some additional examples:

declare function takeA(a: 'a'): void;
declare function takeB(b: 'b'); void;

function f2<T extends 'a' | 'b'>(x: T) {
    if (x === 'a') {
        takeA(x);  // x narrowed to 'a' (error before this PR)
    }
    else {
        takeB(x);  // x narrowed to 'b' (error before this PR)
    }
}

type A = { kind: 'a', value: string };
type B = { kind: 'b', value: number };

function f3<T extends A | B>(x: T) {
    if (x.kind === 'a') {
        x.value;  // Narrowed to string (wasn't narrowed before this PR)
    }
    else {
        x.value;  // Narrowed to number (wasn't narrowed before this PR)
    }
}

Fixes #13995.
Fixes #20375.
Fixes #42939.

@ahejlsberg
Copy link
Member Author

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

@typescript-bot
Copy link
Collaborator

typescript-bot commented Mar 10, 2021

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

@typescript-bot
Copy link
Collaborator

typescript-bot commented Mar 10, 2021

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

Update: The results are in!

@typescript-bot
Copy link
Collaborator

typescript-bot commented Mar 10, 2021

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

@typescript-bot
Copy link
Collaborator

typescript-bot commented Mar 10, 2021

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

Update: The results are in!

@typescript-bot
Copy link
Collaborator

typescript-bot commented Mar 10, 2021

Heya @ahejlsberg, I've started to run the parallelized community code test suite on this PR at a0fbf5c. You can monitor the build here.

@typescript-bot
Copy link
Collaborator

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

Here they are:

Comparison Report - master..43183

Metric master 43183 Delta Best Worst
Angular - node (v10.16.3, x64)
Memory used 348,602k (± 0.03%) 348,691k (± 0.03%) +89k (+ 0.03%) 348,517k 348,893k
Parse Time 1.92s (± 0.52%) 1.92s (± 0.58%) -0.00s (- 0.16%) 1.90s 1.94s
Bind Time 0.83s (± 0.71%) 0.83s (± 0.36%) -0.01s (- 0.72%) 0.82s 0.83s
Check Time 5.03s (± 0.56%) 5.05s (± 0.36%) +0.02s (+ 0.44%) 5.01s 5.09s
Emit Time 5.92s (± 0.38%) 5.92s (± 0.77%) -0.00s (- 0.07%) 5.83s 6.02s
Total Time 13.70s (± 0.34%) 13.71s (± 0.39%) +0.01s (+ 0.07%) 13.65s 13.85s
Compiler-Unions - node (v10.16.3, x64)
Memory used 204,777k (± 0.04%) 203,960k (± 0.04%) -817k (- 0.40%) 203,739k 204,132k
Parse Time 0.78s (± 0.86%) 0.77s (± 0.44%) -0.00s (- 0.51%) 0.77s 0.78s
Bind Time 0.53s (± 0.90%) 0.52s (± 1.18%) -0.01s (- 1.14%) 0.51s 0.53s
Check Time 7.45s (± 0.66%) 7.39s (± 0.64%) -0.06s (- 0.78%) 7.29s 7.49s
Emit Time 2.61s (± 1.12%) 2.59s (± 1.12%) -0.02s (- 0.69%) 2.52s 2.65s
Total Time 11.36s (± 0.52%) 11.27s (± 0.55%) -0.08s (- 0.74%) 11.13s 11.38s
Monaco - node (v10.16.3, x64)
Memory used 356,547k (± 0.01%) 356,594k (± 0.03%) +47k (+ 0.01%) 356,373k 356,783k
Parse Time 1.56s (± 0.44%) 1.55s (± 0.57%) -0.01s (- 0.58%) 1.53s 1.56s
Bind Time 0.74s (± 0.68%) 0.73s (± 0.65%) -0.00s (- 0.27%) 0.72s 0.74s
Check Time 5.20s (± 0.38%) 5.17s (± 0.78%) -0.04s (- 0.71%) 5.07s 5.24s
Emit Time 3.12s (± 0.82%) 3.12s (± 0.75%) -0.01s (- 0.16%) 3.08s 3.18s
Total Time 10.61s (± 0.39%) 10.56s (± 0.51%) -0.05s (- 0.46%) 10.43s 10.69s
TFS - node (v10.16.3, x64)
Memory used 308,965k (± 0.02%) 308,965k (± 0.02%) -0k (- 0.00%) 308,817k 309,142k
Parse Time 1.22s (± 0.67%) 1.21s (± 0.43%) -0.01s (- 0.66%) 1.20s 1.22s
Bind Time 0.69s (± 0.69%) 0.69s (± 0.72%) +0.00s (+ 0.29%) 0.69s 0.71s
Check Time 4.70s (± 0.67%) 4.67s (± 0.41%) -0.03s (- 0.55%) 4.64s 4.72s
Emit Time 3.28s (± 1.06%) 3.25s (± 0.80%) -0.03s (- 0.92%) 3.19s 3.30s
Total Time 9.88s (± 0.62%) 9.82s (± 0.34%) -0.06s (- 0.61%) 9.76s 9.91s
material-ui - node (v10.16.3, x64)
Memory used 501,568k (± 0.01%) 501,610k (± 0.01%) +41k (+ 0.01%) 501,435k 501,729k
Parse Time 1.98s (± 0.38%) 1.98s (± 0.44%) -0.00s (- 0.05%) 1.96s 2.00s
Bind Time 0.65s (± 1.29%) 0.65s (± 1.40%) +0.00s (+ 0.62%) 0.63s 0.67s
Check Time 14.26s (± 0.80%) 14.18s (± 0.40%) -0.09s (- 0.60%) 14.06s 14.29s
Emit Time 0.00s (± 0.00%) 0.00s (± 0.00%) 0.00s ( NaN%) 0.00s 0.00s
Total Time 16.89s (± 0.66%) 16.81s (± 0.37%) -0.08s (- 0.50%) 16.69s 16.94s
Angular - node (v12.1.0, x64)
Memory used 326,249k (± 0.02%) 326,236k (± 0.02%) -13k (- 0.00%) 326,061k 326,374k
Parse Time 1.91s (± 0.46%) 1.91s (± 0.80%) 0.00s ( 0.00%) 1.87s 1.93s
Bind Time 0.81s (± 0.83%) 0.81s (± 0.49%) +0.00s (+ 0.25%) 0.80s 0.82s
Check Time 4.93s (± 0.41%) 4.92s (± 0.45%) -0.01s (- 0.28%) 4.86s 4.98s
Emit Time 5.97s (± 0.59%) 5.96s (± 0.74%) -0.01s (- 0.25%) 5.90s 6.08s
Total Time 13.61s (± 0.46%) 13.59s (± 0.48%) -0.03s (- 0.21%) 13.42s 13.75s
Compiler-Unions - node (v12.1.0, x64)
Memory used 191,506k (± 0.07%) 190,446k (± 0.07%) -1,061k (- 0.55%) 189,942k 190,613k
Parse Time 0.77s (± 0.84%) 0.77s (± 0.76%) -0.00s (- 0.13%) 0.76s 0.78s
Bind Time 0.52s (± 0.65%) 0.52s (± 0.77%) -0.00s (- 0.76%) 0.51s 0.53s
Check Time 6.90s (± 0.67%) 6.89s (± 0.69%) -0.01s (- 0.17%) 6.78s 6.99s
Emit Time 2.56s (± 0.93%) 2.55s (± 0.92%) -0.01s (- 0.47%) 2.50s 2.61s
Total Time 10.76s (± 0.45%) 10.73s (± 0.53%) -0.03s (- 0.26%) 10.57s 10.85s
Monaco - node (v12.1.0, x64)
Memory used 339,016k (± 0.01%) 339,053k (± 0.02%) +37k (+ 0.01%) 338,923k 339,192k
Parse Time 1.53s (± 0.55%) 1.52s (± 0.57%) -0.01s (- 0.59%) 1.50s 1.54s
Bind Time 0.72s (± 0.86%) 0.71s (± 0.51%) -0.01s (- 0.97%) 0.71s 0.72s
Check Time 5.03s (± 0.48%) 4.97s (± 0.41%) -0.06s (- 1.27%) 4.93s 5.01s
Emit Time 3.12s (± 0.58%) 3.09s (± 0.59%) -0.03s (- 0.83%) 3.06s 3.14s
Total Time 10.40s (± 0.28%) 10.31s (± 0.27%) -0.10s (- 0.94%) 10.24s 10.37s
TFS - node (v12.1.0, x64)
Memory used 293,124k (± 0.02%) 293,068k (± 0.01%) -57k (- 0.02%) 293,011k 293,141k
Parse Time 1.21s (± 1.19%) 1.22s (± 0.73%) +0.01s (+ 0.66%) 1.19s 1.23s
Bind Time 0.68s (± 0.87%) 0.68s (± 0.70%) -0.00s (- 0.15%) 0.67s 0.69s
Check Time 4.61s (± 0.46%) 4.55s (± 0.50%) -0.06s (- 1.30%) 4.49s 4.59s
Emit Time 3.16s (± 0.82%) 3.15s (± 0.86%) -0.01s (- 0.44%) 3.06s 3.20s
Total Time 9.66s (± 0.45%) 9.59s (± 0.32%) -0.06s (- 0.67%) 9.53s 9.69s
material-ui - node (v12.1.0, x64)
Memory used 479,599k (± 0.01%) 479,336k (± 0.07%) -263k (- 0.05%) 478,393k 479,758k
Parse Time 2.00s (± 0.43%) 1.98s (± 0.38%) -0.01s (- 0.70%) 1.97s 2.00s
Bind Time 0.64s (± 0.52%) 0.64s (± 0.97%) -0.00s (- 0.16%) 0.63s 0.65s
Check Time 12.84s (± 0.66%) 13.00s (± 1.15%) +0.15s (+ 1.18%) 12.71s 13.31s
Emit Time 0.00s (± 0.00%) 0.00s (± 0.00%) 0.00s ( NaN%) 0.00s 0.00s
Total Time 15.48s (± 0.56%) 15.62s (± 0.99%) +0.14s (+ 0.88%) 15.34s 15.94s
Angular - node (v14.15.1, x64)
Memory used 324,912k (± 0.01%) 324,931k (± 0.01%) +19k (+ 0.01%) 324,872k 325,042k
Parse Time 1.90s (± 0.29%) 1.91s (± 0.86%) +0.01s (+ 0.42%) 1.88s 1.96s
Bind Time 0.84s (± 0.40%) 0.85s (± 0.76%) +0.01s (+ 1.07%) 0.84s 0.86s
Check Time 4.91s (± 0.35%) 4.92s (± 0.24%) +0.00s (+ 0.08%) 4.89s 4.94s
Emit Time 6.28s (± 0.68%) 6.27s (± 0.55%) -0.01s (- 0.13%) 6.22s 6.39s
Total Time 13.93s (± 0.39%) 13.95s (± 0.27%) +0.01s (+ 0.09%) 13.89s 14.07s
Compiler-Unions - node (v14.15.1, x64)
Memory used 191,073k (± 0.02%) 190,058k (± 0.01%) -1,015k (- 0.53%) 190,003k 190,115k
Parse Time 0.79s (± 0.62%) 0.80s (± 0.86%) +0.00s (+ 0.25%) 0.78s 0.81s
Bind Time 0.55s (± 1.01%) 0.55s (± 0.00%) -0.00s (- 0.36%) 0.55s 0.55s
Check Time 6.97s (± 0.52%) 6.94s (± 0.20%) -0.03s (- 0.49%) 6.91s 6.97s
Emit Time 2.54s (± 0.60%) 2.53s (± 0.89%) -0.00s (- 0.08%) 2.49s 2.58s
Total Time 10.85s (± 0.41%) 10.81s (± 0.21%) -0.04s (- 0.39%) 10.77s 10.87s
Monaco - node (v14.15.1, x64)
Memory used 338,095k (± 0.00%) 338,053k (± 0.01%) -42k (- 0.01%) 338,011k 338,095k
Parse Time 1.55s (± 0.43%) 1.55s (± 0.44%) +0.00s (+ 0.26%) 1.54s 1.57s
Bind Time 0.75s (± 0.89%) 0.75s (± 0.67%) -0.00s (- 0.67%) 0.74s 0.76s
Check Time 4.94s (± 0.50%) 4.92s (± 0.15%) -0.02s (- 0.45%) 4.90s 4.93s
Emit Time 3.15s (± 0.70%) 3.14s (± 0.46%) -0.01s (- 0.35%) 3.12s 3.19s
Total Time 10.39s (± 0.41%) 10.36s (± 0.19%) -0.03s (- 0.31%) 10.33s 10.42s
TFS - node (v14.15.1, x64)
Memory used 292,227k (± 0.01%) 292,252k (± 0.01%) +25k (+ 0.01%) 292,214k 292,306k
Parse Time 1.25s (± 0.93%) 1.24s (± 1.16%) -0.01s (- 0.96%) 1.21s 1.27s
Bind Time 0.72s (± 0.97%) 0.71s (± 0.70%) -0.00s (- 0.56%) 0.71s 0.73s
Check Time 4.56s (± 0.39%) 4.57s (± 0.33%) +0.01s (+ 0.18%) 4.54s 4.60s
Emit Time 3.24s (± 0.70%) 3.24s (± 0.62%) -0.00s (- 0.06%) 3.21s 3.30s
Total Time 9.78s (± 0.35%) 9.77s (± 0.23%) -0.01s (- 0.07%) 9.72s 9.82s
material-ui - node (v14.15.1, x64)
Memory used 477,936k (± 0.00%) 477,719k (± 0.07%) -217k (- 0.05%) 476,751k 478,019k
Parse Time 2.06s (± 0.69%) 2.06s (± 0.55%) +0.00s (+ 0.15%) 2.04s 2.08s
Bind Time 0.70s (± 0.83%) 0.70s (± 0.52%) -0.00s (- 0.14%) 0.69s 0.70s
Check Time 12.99s (± 0.70%) 12.97s (± 0.79%) -0.02s (- 0.17%) 12.76s 13.17s
Emit Time 0.00s (± 0.00%) 0.00s (± 0.00%) 0.00s ( NaN%) 0.00s 0.00s
Total Time 15.74s (± 0.64%) 15.72s (± 0.65%) -0.02s (- 0.14%) 15.54s 15.93s
System
Machine Namets-ci-ubuntu
Platformlinux 4.4.0-198-generic
Architecturex64
Available Memory16 GB
Available Memory5 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)
Benchmark Name Iterations
Current 43183 10
Baseline master 10

Developer Information:

Download Benchmark

@typescript-bot
Copy link
Collaborator

The user suite test run you requested has finished and failed. I've opened a PR with the baseline diff from master.

@typescript-bot
Copy link
Collaborator

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

Here they are:

Comparison Report - master..43183

Metric master 43183 Delta Best Worst
Angular - node (v14.15.1, x64)
Memory used 324,912k (± 0.01%) 324,935k (± 0.01%) +23k (+ 0.01%) 324,842k 325,009k
Parse Time 1.90s (± 0.29%) 1.91s (± 0.43%) +0.01s (+ 0.47%) 1.89s 1.93s
Bind Time 0.84s (± 0.40%) 0.85s (± 0.76%) +0.01s (+ 0.59%) 0.84s 0.86s
Check Time 4.91s (± 0.35%) 4.91s (± 0.65%) -0.00s (- 0.08%) 4.85s 4.99s
Emit Time 6.28s (± 0.68%) 6.27s (± 0.40%) -0.01s (- 0.19%) 6.21s 6.34s
Total Time 13.93s (± 0.39%) 13.93s (± 0.35%) -0.00s (- 0.02%) 13.82s 14.04s
Compiler-Unions - node (v14.15.1, x64)
Memory used 191,073k (± 0.02%) 190,043k (± 0.01%) -1,030k (- 0.54%) 189,997k 190,118k
Parse Time 0.79s (± 0.62%) 0.80s (± 0.86%) +0.00s (+ 0.25%) 0.78s 0.81s
Bind Time 0.55s (± 1.01%) 0.56s (± 0.89%) +0.00s (+ 0.72%) 0.55s 0.57s
Check Time 6.97s (± 0.52%) 7.02s (± 0.76%) +0.05s (+ 0.75%) 6.94s 7.20s
Emit Time 2.54s (± 0.60%) 2.54s (± 0.39%) +0.00s (+ 0.12%) 2.52s 2.56s
Total Time 10.85s (± 0.41%) 10.91s (± 0.55%) +0.06s (+ 0.55%) 10.82s 11.11s
Monaco - node (v14.15.1, x64)
Memory used 338,095k (± 0.00%) 338,063k (± 0.01%) -32k (- 0.01%) 338,015k 338,109k
Parse Time 1.55s (± 0.43%) 1.56s (± 0.73%) +0.01s (+ 0.52%) 1.54s 1.59s
Bind Time 0.75s (± 0.89%) 0.75s (± 0.80%) -0.00s (- 0.53%) 0.74s 0.76s
Check Time 4.94s (± 0.50%) 4.93s (± 0.42%) -0.01s (- 0.18%) 4.88s 4.97s
Emit Time 3.15s (± 0.70%) 3.15s (± 0.46%) -0.00s (- 0.03%) 3.12s 3.18s
Total Time 10.39s (± 0.41%) 10.38s (± 0.26%) -0.01s (- 0.07%) 10.31s 10.43s
TFS - node (v14.15.1, x64)
Memory used 292,227k (± 0.01%) 292,248k (± 0.01%) +21k (+ 0.01%) 292,192k 292,278k
Parse Time 1.25s (± 0.93%) 1.26s (± 0.89%) +0.01s (+ 0.56%) 1.24s 1.30s
Bind Time 0.72s (± 0.97%) 0.71s (± 1.06%) -0.01s (- 0.70%) 0.70s 0.74s
Check Time 4.56s (± 0.39%) 4.57s (± 0.35%) +0.00s (+ 0.09%) 4.53s 4.60s
Emit Time 3.24s (± 0.70%) 3.25s (± 0.56%) +0.00s (+ 0.09%) 3.21s 3.28s
Total Time 9.78s (± 0.35%) 9.79s (± 0.38%) +0.01s (+ 0.11%) 9.73s 9.92s
material-ui - node (v14.15.1, x64)
Memory used 477,936k (± 0.00%) 477,953k (± 0.00%) +16k (+ 0.00%) 477,885k 477,980k
Parse Time 2.06s (± 0.69%) 2.06s (± 0.60%) +0.01s (+ 0.34%) 2.04s 2.10s
Bind Time 0.70s (± 0.83%) 0.69s (± 1.19%) -0.00s (- 0.43%) 0.68s 0.71s
Check Time 12.99s (± 0.70%) 12.88s (± 0.34%) -0.11s (- 0.82%) 12.79s 12.97s
Emit Time 0.00s (± 0.00%) 0.00s (± 0.00%) 0.00s ( NaN%) 0.00s 0.00s
Total Time 15.74s (± 0.64%) 15.64s (± 0.29%) -0.10s (- 0.65%) 15.52s 15.73s
System
Machine Namets-ci-ubuntu
Platformlinux 4.4.0-198-generic
Architecturex64
Available Memory16 GB
Available Memory5 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)
Benchmark Name Iterations
Current 43183 10
Baseline master 10

Developer Information:

Download Benchmark

function getConstraintForReference(type: Type, reference: Identifier | ElementAccessExpression | PropertyAccessExpression | QualifiedName, checkMode: CheckMode | undefined) {
// When the type of a reference is or contains an instantiable type with a union type constraint, and
// when the reference is in a constraint position (where it is known we'll obtain the apparent type) or
// has a contextual type containing no instantiables (meaning constraints will determine assignability),
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// has a contextual type containing no instantiables (meaning constraints will determine assignability),
// has a contextual type containing no top-level instantiables (meaning constraints will determine assignability),

or

Suggested change
// has a contextual type containing no instantiables (meaning constraints will determine assignability),
// has a contextual type containing no immediate instantiables (meaning constraints will determine assignability),

@DanielRosenwasser
Copy link
Member

@typescript-bot pack this

@typescript-bot
Copy link
Collaborator

typescript-bot commented Mar 10, 2021

Heya @DanielRosenwasser, I've started to run the tarball bundle task on this PR at 1a695e9. You can monitor the build here.

@typescript-bot
Copy link
Collaborator

typescript-bot commented Mar 10, 2021

Hey @DanielRosenwasser, 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/98224/artifacts?artifactName=tgz&fileId=266017171922858A31CD3EFD83E393EF6E56EB48D53ED8C01365E5A0113A6F5602&fileName=/typescript-4.3.0-insiders.20210310.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]".;

@DanielRosenwasser
Copy link
Member

@ahejlsberg might be worth adding in the following test cases - f2 now works correctly.

interface Box<T> {
    item: T;
}

declare function isBox(x: any): x is Box<unknown>;
declare function isUndefined(x: unknown): x is undefined;
declare function unbox<T>(x: Box<T>): T;

function f1<T extends Box<T> | undefined>(x: T) {
    if (isBox(x)) {
        unbox(x);
    }
}

function f2<T extends Box<T> | undefined>(x: T) {
    if (!isUndefined(x)) {
        unbox(x);
    }
}

function f3<T extends Box<T> | undefined>(x: T) {
    if (!isBox(x)) {
        // error
        unbox(x);
    }
}

function f4<T extends Box<T> | undefined>(x: T) {
    if (isUndefined(x)) {
        // error
        unbox(x);
    }
}

@ahejlsberg
Copy link
Member Author

@DanielRosenwasser Will do.

@ahejlsberg
Copy link
Member Author

ahejlsberg commented Mar 11, 2021

Performance looks to be unaffected. RWC test suite looks good too, only change is a couple of error messages that now show constraint types instead of generic types (as expected).

RaynalHugo added a commit to labelflow/labelflow that referenced this pull request Jul 23, 2021
chriskrycho added a commit to true-myth/true-myth that referenced this pull request Apr 22, 2022
TS 4.7 catches a class of error which 4.6 and earlier did not, courtesy
of microsoft/TypeScript#43183: if the type passed does not implement
`toString()`, it notices, because it no longer defaults to falling back
to `{}`.

Fixes #330
chriskrycho added a commit to true-myth/true-myth that referenced this pull request Apr 22, 2022
TS 4.7 catches a class of error which 4.6 and earlier did not, courtesy
of microsoft/TypeScript#43183: if the type passed does not implement
`toString()`, it notices, because it no longer defaults to falling back
to `{}`.

To resolve this, *loosen* the constraints on what is acceptable as
input to `toString`, by making the implementation itself more robust.
Doing so also fixes a bug with the output for `toString` when working
with strings: previously if you had `Maybe("a string")`, the `toString`
output would be `'Maybe(a string)'`; it is now `'Maybe("a string")'`.

Fixes #330
chriskrycho added a commit to true-myth/true-myth that referenced this pull request Apr 22, 2022
TS 4.7 catches a class of error which 4.6 and earlier did not, courtesy
of microsoft/TypeScript#43183: if the type passed does not implement
`toString()`, it notices, because it no longer defaults to falling back
to `{}`.

To resolve this, *loosen* the constraints on what is acceptable as
input to `toString`, by making the implementation itself more robust.
Doing so also fixes a bug with the output for `toString` when working
with strings: previously if you had `Maybe("a string")`, the `toString`
output would be `'Maybe(a string)'`; it is now `'Maybe("a string")'`.

Fixes #330
chriskrycho added a commit to true-myth/true-myth that referenced this pull request Apr 22, 2022
(cherry picked from commit 25adb1a)

---

Original message:

Add support for TypeScript 4.7

TS 4.7 catches a class of error which 4.6 and earlier did not, courtesy
of microsoft/TypeScript#43183: if the type passed does not implement
`toString()`, it notices, because it no longer defaults to falling back
to `{}`.

To resolve this, *loosen* the constraints on what is acceptable as
input to `toString`, by making the implementation itself more robust.
Doing so also fixes a bug with the output for `toString` when working
with strings: previously if you had `Maybe("a string")`, the `toString`
output would be `'Maybe(a string)'`; it is now `'Maybe("a string")'`.

Fixes #330
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Author: Team For Backlog Bug PRs that fix a backlog bug For Milestone Bug PRs that fix a bug with a specific milestone
Projects
None yet
8 participants