Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add unmeasurable variance kind for marking types whose variance resul…
…t is unreliable (#30416) * Add unmeasurable variance kind for marking types whose variance result is unreliable * Remove now-unneeded nongeneric checks * Add rule allowing `Readonly<any>` to be `any` instead of `{readonly [index: string]: any}` * All Unmeasurable variances to still shortcut structural comparisons in some cases * Separate unmeasurable from unreliable to reduce the impact of this change, for now * Fix lint * Remove Readonly<any> -> any callout * Add fix for circularity error triggered by deep signature return type comparisons with `this` types
- Loading branch information
Showing
23 changed files
with
1,092 additions
and
57 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
32 changes: 32 additions & 0 deletions
32
tests/baselines/reference/checkInfiniteExpansionTermination.errors.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
tests/cases/compiler/checkInfiniteExpansionTermination.ts(16,1): error TS2322: Type 'ISubject<Bar>' is not assignable to type 'IObservable<Foo>'. | ||
Types of property 'n' are incompatible. | ||
Type 'IObservable<Bar[]>' is not assignable to type 'IObservable<Foo[]>'. | ||
Type 'Bar[]' is not assignable to type 'Foo[]'. | ||
Property 'x' is missing in type 'Bar' but required in type 'Foo'. | ||
|
||
|
||
==== tests/cases/compiler/checkInfiniteExpansionTermination.ts (1 errors) ==== | ||
// Regression test for #1002 | ||
// Before fix this code would cause infinite loop | ||
|
||
interface IObservable<T> { | ||
n: IObservable<T[]>; // Needed, must be T[] | ||
} | ||
|
||
// Needed | ||
interface ISubject<T> extends IObservable<T> { } | ||
|
||
interface Foo { x } | ||
interface Bar { y } | ||
|
||
var values: IObservable<Foo>; | ||
var values2: ISubject<Bar>; | ||
values = values2; | ||
~~~~~~ | ||
!!! error TS2322: Type 'ISubject<Bar>' is not assignable to type 'IObservable<Foo>'. | ||
!!! error TS2322: Types of property 'n' are incompatible. | ||
!!! error TS2322: Type 'IObservable<Bar[]>' is not assignable to type 'IObservable<Foo[]>'. | ||
!!! error TS2322: Type 'Bar[]' is not assignable to type 'Foo[]'. | ||
!!! error TS2322: Property 'x' is missing in type 'Bar' but required in type 'Foo'. | ||
!!! related TS2728 tests/cases/compiler/checkInfiniteExpansionTermination.ts:11:17: 'x' is declared here. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
55 changes: 55 additions & 0 deletions
55
tests/baselines/reference/consistentAliasVsNonAliasRecordBehavior.errors.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
tests/cases/compiler/consistentAliasVsNonAliasRecordBehavior.ts(18,5): error TS2741: Property 'a' is missing in type 'Record<string, string>' but required in type 'Record2<"a", string>'. | ||
tests/cases/compiler/consistentAliasVsNonAliasRecordBehavior.ts(22,5): error TS2741: Property 'a' is missing in type 'Record2<string, string>' but required in type 'Record<"a", string>'. | ||
tests/cases/compiler/consistentAliasVsNonAliasRecordBehavior.ts(34,5): error TS2741: Property 'a' is missing in type 'Record<string, T>' but required in type 'Record2<"a", T>'. | ||
tests/cases/compiler/consistentAliasVsNonAliasRecordBehavior.ts(38,5): error TS2741: Property 'a' is missing in type 'Record2<string, T>' but required in type 'Record<"a", T>'. | ||
|
||
|
||
==== tests/cases/compiler/consistentAliasVsNonAliasRecordBehavior.ts (4 errors) ==== | ||
// TODO: FIXME: All the below cases labeled `no error` _should be an error_, and are only prevented from so being | ||
// by incorrect variance-based relationships | ||
// Ref: https://github.com/Microsoft/TypeScript/issues/29698 | ||
|
||
type Record2<K extends keyof any, T> = { | ||
[P in K]: T; | ||
}; | ||
|
||
function defaultRecord(x: Record<'a', string>, y: Record<string, string>) { | ||
x = y; // no error, but error expected. | ||
} | ||
|
||
function customRecord(x: Record2<'a', string>, y: Record2<string, string>) { | ||
x = y; // no error, but error expected. | ||
} | ||
|
||
function mixed1(x: Record2<'a', string>, y: Record<string, string>) { | ||
x = y; // error | ||
~ | ||
!!! error TS2741: Property 'a' is missing in type 'Record<string, string>' but required in type 'Record2<"a", string>'. | ||
} | ||
|
||
function mixed2(x: Record<'a', string>, y: Record2<string, string>) { | ||
x = y; // error | ||
~ | ||
!!! error TS2741: Property 'a' is missing in type 'Record2<string, string>' but required in type 'Record<"a", string>'. | ||
} | ||
|
||
function defaultRecord2<T>(x: Record<'a', T>, y: Record<string, T>) { | ||
x = y; // no error, but error expected. | ||
} | ||
|
||
function customRecord2<T>(x: Record2<'a', T>, y: Record2<string, T>) { | ||
x = y; // no error, but error expected. | ||
} | ||
|
||
function mixed3<T>(x: Record2<'a', T>, y: Record<string, T>) { | ||
x = y; // error | ||
~ | ||
!!! error TS2741: Property 'a' is missing in type 'Record<string, T>' but required in type 'Record2<"a", T>'. | ||
} | ||
|
||
function mixed4<T>(x: Record<'a', T>, y: Record2<string, T>) { | ||
x = y; // error | ||
~ | ||
!!! error TS2741: Property 'a' is missing in type 'Record2<string, T>' but required in type 'Record<"a", T>'. | ||
} | ||
|
70 changes: 70 additions & 0 deletions
70
tests/baselines/reference/consistentAliasVsNonAliasRecordBehavior.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
//// [consistentAliasVsNonAliasRecordBehavior.ts] | ||
// TODO: FIXME: All the below cases labeled `no error` _should be an error_, and are only prevented from so being | ||
// by incorrect variance-based relationships | ||
// Ref: https://github.com/Microsoft/TypeScript/issues/29698 | ||
|
||
type Record2<K extends keyof any, T> = { | ||
[P in K]: T; | ||
}; | ||
|
||
function defaultRecord(x: Record<'a', string>, y: Record<string, string>) { | ||
x = y; // no error, but error expected. | ||
} | ||
|
||
function customRecord(x: Record2<'a', string>, y: Record2<string, string>) { | ||
x = y; // no error, but error expected. | ||
} | ||
|
||
function mixed1(x: Record2<'a', string>, y: Record<string, string>) { | ||
x = y; // error | ||
} | ||
|
||
function mixed2(x: Record<'a', string>, y: Record2<string, string>) { | ||
x = y; // error | ||
} | ||
|
||
function defaultRecord2<T>(x: Record<'a', T>, y: Record<string, T>) { | ||
x = y; // no error, but error expected. | ||
} | ||
|
||
function customRecord2<T>(x: Record2<'a', T>, y: Record2<string, T>) { | ||
x = y; // no error, but error expected. | ||
} | ||
|
||
function mixed3<T>(x: Record2<'a', T>, y: Record<string, T>) { | ||
x = y; // error | ||
} | ||
|
||
function mixed4<T>(x: Record<'a', T>, y: Record2<string, T>) { | ||
x = y; // error | ||
} | ||
|
||
|
||
//// [consistentAliasVsNonAliasRecordBehavior.js] | ||
// TODO: FIXME: All the below cases labeled `no error` _should be an error_, and are only prevented from so being | ||
// by incorrect variance-based relationships | ||
// Ref: https://github.com/Microsoft/TypeScript/issues/29698 | ||
function defaultRecord(x, y) { | ||
x = y; // no error, but error expected. | ||
} | ||
function customRecord(x, y) { | ||
x = y; // no error, but error expected. | ||
} | ||
function mixed1(x, y) { | ||
x = y; // error | ||
} | ||
function mixed2(x, y) { | ||
x = y; // error | ||
} | ||
function defaultRecord2(x, y) { | ||
x = y; // no error, but error expected. | ||
} | ||
function customRecord2(x, y) { | ||
x = y; // no error, but error expected. | ||
} | ||
function mixed3(x, y) { | ||
x = y; // error | ||
} | ||
function mixed4(x, y) { | ||
x = y; // error | ||
} |
125 changes: 125 additions & 0 deletions
125
tests/baselines/reference/consistentAliasVsNonAliasRecordBehavior.symbols
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
=== tests/cases/compiler/consistentAliasVsNonAliasRecordBehavior.ts === | ||
// TODO: FIXME: All the below cases labeled `no error` _should be an error_, and are only prevented from so being | ||
// by incorrect variance-based relationships | ||
// Ref: https://github.com/Microsoft/TypeScript/issues/29698 | ||
|
||
type Record2<K extends keyof any, T> = { | ||
>Record2 : Symbol(Record2, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 0, 0)) | ||
>K : Symbol(K, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 4, 13)) | ||
>T : Symbol(T, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 4, 33)) | ||
|
||
[P in K]: T; | ||
>P : Symbol(P, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 5, 5)) | ||
>K : Symbol(K, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 4, 13)) | ||
>T : Symbol(T, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 4, 33)) | ||
|
||
}; | ||
|
||
function defaultRecord(x: Record<'a', string>, y: Record<string, string>) { | ||
>defaultRecord : Symbol(defaultRecord, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 6, 2)) | ||
>x : Symbol(x, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 8, 23)) | ||
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) | ||
>y : Symbol(y, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 8, 46)) | ||
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) | ||
|
||
x = y; // no error, but error expected. | ||
>x : Symbol(x, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 8, 23)) | ||
>y : Symbol(y, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 8, 46)) | ||
} | ||
|
||
function customRecord(x: Record2<'a', string>, y: Record2<string, string>) { | ||
>customRecord : Symbol(customRecord, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 10, 1)) | ||
>x : Symbol(x, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 12, 22)) | ||
>Record2 : Symbol(Record2, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 0, 0)) | ||
>y : Symbol(y, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 12, 46)) | ||
>Record2 : Symbol(Record2, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 0, 0)) | ||
|
||
x = y; // no error, but error expected. | ||
>x : Symbol(x, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 12, 22)) | ||
>y : Symbol(y, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 12, 46)) | ||
} | ||
|
||
function mixed1(x: Record2<'a', string>, y: Record<string, string>) { | ||
>mixed1 : Symbol(mixed1, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 14, 1)) | ||
>x : Symbol(x, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 16, 16)) | ||
>Record2 : Symbol(Record2, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 0, 0)) | ||
>y : Symbol(y, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 16, 40)) | ||
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) | ||
|
||
x = y; // error | ||
>x : Symbol(x, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 16, 16)) | ||
>y : Symbol(y, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 16, 40)) | ||
} | ||
|
||
function mixed2(x: Record<'a', string>, y: Record2<string, string>) { | ||
>mixed2 : Symbol(mixed2, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 18, 1)) | ||
>x : Symbol(x, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 20, 16)) | ||
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) | ||
>y : Symbol(y, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 20, 39)) | ||
>Record2 : Symbol(Record2, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 0, 0)) | ||
|
||
x = y; // error | ||
>x : Symbol(x, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 20, 16)) | ||
>y : Symbol(y, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 20, 39)) | ||
} | ||
|
||
function defaultRecord2<T>(x: Record<'a', T>, y: Record<string, T>) { | ||
>defaultRecord2 : Symbol(defaultRecord2, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 22, 1)) | ||
>T : Symbol(T, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 24, 24)) | ||
>x : Symbol(x, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 24, 27)) | ||
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) | ||
>T : Symbol(T, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 24, 24)) | ||
>y : Symbol(y, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 24, 45)) | ||
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) | ||
>T : Symbol(T, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 24, 24)) | ||
|
||
x = y; // no error, but error expected. | ||
>x : Symbol(x, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 24, 27)) | ||
>y : Symbol(y, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 24, 45)) | ||
} | ||
|
||
function customRecord2<T>(x: Record2<'a', T>, y: Record2<string, T>) { | ||
>customRecord2 : Symbol(customRecord2, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 26, 1)) | ||
>T : Symbol(T, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 28, 23)) | ||
>x : Symbol(x, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 28, 26)) | ||
>Record2 : Symbol(Record2, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 0, 0)) | ||
>T : Symbol(T, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 28, 23)) | ||
>y : Symbol(y, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 28, 45)) | ||
>Record2 : Symbol(Record2, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 0, 0)) | ||
>T : Symbol(T, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 28, 23)) | ||
|
||
x = y; // no error, but error expected. | ||
>x : Symbol(x, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 28, 26)) | ||
>y : Symbol(y, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 28, 45)) | ||
} | ||
|
||
function mixed3<T>(x: Record2<'a', T>, y: Record<string, T>) { | ||
>mixed3 : Symbol(mixed3, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 30, 1)) | ||
>T : Symbol(T, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 32, 16)) | ||
>x : Symbol(x, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 32, 19)) | ||
>Record2 : Symbol(Record2, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 0, 0)) | ||
>T : Symbol(T, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 32, 16)) | ||
>y : Symbol(y, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 32, 38)) | ||
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) | ||
>T : Symbol(T, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 32, 16)) | ||
|
||
x = y; // error | ||
>x : Symbol(x, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 32, 19)) | ||
>y : Symbol(y, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 32, 38)) | ||
} | ||
|
||
function mixed4<T>(x: Record<'a', T>, y: Record2<string, T>) { | ||
>mixed4 : Symbol(mixed4, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 34, 1)) | ||
>T : Symbol(T, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 36, 16)) | ||
>x : Symbol(x, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 36, 19)) | ||
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) | ||
>T : Symbol(T, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 36, 16)) | ||
>y : Symbol(y, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 36, 37)) | ||
>Record2 : Symbol(Record2, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 0, 0)) | ||
>T : Symbol(T, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 36, 16)) | ||
|
||
x = y; // error | ||
>x : Symbol(x, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 36, 19)) | ||
>y : Symbol(y, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 36, 37)) | ||
} | ||
|
Oops, something went wrong.