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

Elaborate array and tuple relation errors #30916

Merged
merged 1 commit into from Apr 15, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
49 changes: 44 additions & 5 deletions src/compiler/checker.ts
Expand Up @@ -12246,6 +12246,40 @@ namespace ts {
}
}

/**
* Try and elaborate array and tuple errors. Returns false
* if we have found an elaboration, or we should ignore
* any other elaborations when relating the `source` and
* `target` types.
*
* @param source
* @param target
* @param reportErrors
*/
function tryElaborateArrayLikeErrors(source: Type, target: Type, reportErrors: boolean): boolean {
if (isTupleLikeType(source)) {
const sourceTuple: TupleType | undefined = (source as TupleTypeReference).target;
if (sourceTuple && sourceTuple.readonly && isArrayOrTupleLikeType(target) &&
(!isReadonlyArrayType(target) || isTupleType(target) && !target.target.readonly)) {
if (reportErrors) {
reportError(Diagnostics.The_type_0_is_readonly_and_cannot_be_assigned_to_the_mutable_type_1, typeToString(source), typeToString(target));
}
return false;
}
return isArrayLikeType(target);
}
if (isTupleLikeType(target)) {
return isArrayLikeType(source);
}
if (isReadonlyArrayType(source) && isArrayType(target) && !isReadonlyArrayType(target)) {
if (reportErrors) {
reportError(Diagnostics.The_type_0_is_readonly_and_cannot_be_assigned_to_the_mutable_type_1, typeToString(source), typeToString(target));
}
return false;
}
return true;
}

function isUnionOrIntersectionTypeWithoutNullableConstituents(type: Type): boolean {
if (!(type.flags & TypeFlags.UnionOrIntersection)) {
return false;
Expand Down Expand Up @@ -12418,6 +12452,9 @@ namespace ts {
if (!result && reportErrors) {
const maybeSuppress = suppressNextError;
suppressNextError = false;
if (source.flags & TypeFlags.Object && target.flags & TypeFlags.Object) {
tryElaborateArrayLikeErrors(source, target, reportErrors);
}
if (source.flags & TypeFlags.Object && target.flags & TypeFlags.Primitive) {
tryElaborateErrorsForPrimitivesAndObjects(source, target);
}
Expand Down Expand Up @@ -13148,11 +13185,13 @@ namespace ts {
associateRelatedInfo(createDiagnosticForNode(unmatchedProperty.declarations[0], Diagnostics._0_is_declared_here, propName));
}
}
else if (props.length > 5) { // arbitrary cutoff for too-long list form
reportError(Diagnostics.Type_0_is_missing_the_following_properties_from_type_1_Colon_2_and_3_more, typeToString(source), typeToString(target), map(props.slice(0, 4), p => symbolToString(p)).join(", "), props.length - 4);
}
else {
reportError(Diagnostics.Type_0_is_missing_the_following_properties_from_type_1_Colon_2, typeToString(source), typeToString(target), map(props, p => symbolToString(p)).join(", "));
else if (tryElaborateArrayLikeErrors(source, target, /*reportErrors*/ false)) {
if (props.length > 5) { // arbitrary cutoff for too-long list form
reportError(Diagnostics.Type_0_is_missing_the_following_properties_from_type_1_Colon_2_and_3_more, typeToString(source), typeToString(target), map(props.slice(0, 4), p => symbolToString(p)).join(", "), props.length - 4);
}
else {
reportError(Diagnostics.Type_0_is_missing_the_following_properties_from_type_1_Colon_2, typeToString(source), typeToString(target), map(props, p => symbolToString(p)).join(", "));
}
}
}
return Ternary.False;
Expand Down
6 changes: 5 additions & 1 deletion src/compiler/diagnosticMessages.json
Expand Up @@ -2943,7 +2943,11 @@
"category": "Error",
"code": 4103
},

"The type '{0}' is 'readonly' and cannot be assigned to the mutable type '{1}'.": {
"category": "Error",
"code": 4104
},

"The current host does not support the '{0}' option.": {
"category": "Error",
"code": 5001
Expand Down
4 changes: 1 addition & 3 deletions tests/baselines/reference/iterableArrayPattern10.errors.txt
@@ -1,5 +1,4 @@
tests/cases/conformance/es6/destructuring/iterableArrayPattern10.ts(17,5): error TS2345: Argument of type 'FooIterator' is not assignable to parameter of type '[any, any]'.
Type 'FooIterator' is missing the following properties from type '[any, any]': 0, 1, length, pop, and 26 more.


==== tests/cases/conformance/es6/destructuring/iterableArrayPattern10.ts (1 errors) ====
Expand All @@ -21,5 +20,4 @@ tests/cases/conformance/es6/destructuring/iterableArrayPattern10.ts(17,5): error
function fun([a, b]) { }
fun(new FooIterator);
~~~~~~~~~~~~~~~
!!! error TS2345: Argument of type 'FooIterator' is not assignable to parameter of type '[any, any]'.
!!! error TS2345: Type 'FooIterator' is missing the following properties from type '[any, any]': 0, 1, length, pop, and 26 more.
!!! error TS2345: Argument of type 'FooIterator' is not assignable to parameter of type '[any, any]'.
4 changes: 1 addition & 3 deletions tests/baselines/reference/iterableArrayPattern13.errors.txt
@@ -1,5 +1,4 @@
tests/cases/conformance/es6/destructuring/iterableArrayPattern13.ts(17,5): error TS2345: Argument of type 'FooIterator' is not assignable to parameter of type '[any, ...any[]]'.
Type 'FooIterator' is missing the following properties from type '[any, ...any[]]': 0, length, pop, push, and 25 more.


==== tests/cases/conformance/es6/destructuring/iterableArrayPattern13.ts (1 errors) ====
Expand All @@ -21,5 +20,4 @@ tests/cases/conformance/es6/destructuring/iterableArrayPattern13.ts(17,5): error
function fun([a, ...b]) { }
fun(new FooIterator);
~~~~~~~~~~~~~~~
!!! error TS2345: Argument of type 'FooIterator' is not assignable to parameter of type '[any, ...any[]]'.
!!! error TS2345: Type 'FooIterator' is missing the following properties from type '[any, ...any[]]': 0, length, pop, push, and 25 more.
!!! error TS2345: Argument of type 'FooIterator' is not assignable to parameter of type '[any, ...any[]]'.
2 changes: 0 additions & 2 deletions tests/baselines/reference/iterableArrayPattern16.errors.txt
@@ -1,5 +1,4 @@
tests/cases/conformance/es6/destructuring/iterableArrayPattern16.ts(2,5): error TS2345: Argument of type 'FooIterator' is not assignable to parameter of type '[Bar, Bar]'.
Type 'FooIterator' is missing the following properties from type '[Bar, Bar]': 0, 1, length, pop, and 26 more.
tests/cases/conformance/es6/destructuring/iterableArrayPattern16.ts(2,12): error TS2449: Class 'FooIteratorIterator' used before its declaration.


Expand All @@ -8,7 +7,6 @@ tests/cases/conformance/es6/destructuring/iterableArrayPattern16.ts(2,12): error
fun(...new FooIteratorIterator);
~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2345: Argument of type 'FooIterator' is not assignable to parameter of type '[Bar, Bar]'.
!!! error TS2345: Type 'FooIterator' is missing the following properties from type '[Bar, Bar]': 0, 1, length, pop, and 26 more.
~~~~~~~~~~~~~~~~~~~
!!! error TS2449: Class 'FooIteratorIterator' used before its declaration.
!!! related TS2728 tests/cases/conformance/es6/destructuring/iterableArrayPattern16.ts:18:7: 'FooIteratorIterator' is declared here.
Expand Down
4 changes: 1 addition & 3 deletions tests/baselines/reference/iterableArrayPattern26.errors.txt
@@ -1,10 +1,8 @@
tests/cases/conformance/es6/destructuring/iterableArrayPattern26.ts(2,21): error TS2345: Argument of type 'Map<string, number>' is not assignable to parameter of type '[string, number]'.
Type 'Map<string, number>' is missing the following properties from type '[string, number]': 0, 1, length, pop, and 22 more.


==== tests/cases/conformance/es6/destructuring/iterableArrayPattern26.ts (1 errors) ====
function takeFirstTwoEntries(...[[k1, v1], [k2, v2]]: [string, number][]) { }
takeFirstTwoEntries(new Map([["", 0], ["hello", 1]]));
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2345: Argument of type 'Map<string, number>' is not assignable to parameter of type '[string, number]'.
!!! error TS2345: Type 'Map<string, number>' is missing the following properties from type '[string, number]': 0, 1, length, pop, and 22 more.
!!! error TS2345: Argument of type 'Map<string, number>' is not assignable to parameter of type '[string, number]'.
12 changes: 6 additions & 6 deletions tests/baselines/reference/readonlyArraysAndTuples.errors.txt
Expand Up @@ -2,11 +2,11 @@ tests/cases/conformance/types/tuple/readonlyArraysAndTuples.ts(9,12): error TS13
tests/cases/conformance/types/tuple/readonlyArraysAndTuples.ts(10,15): error TS1354: 'readonly' type modifier is only permitted on array and tuple literal types.
tests/cases/conformance/types/tuple/readonlyArraysAndTuples.ts(11,12): error TS1354: 'readonly' type modifier is only permitted on array and tuple literal types.
tests/cases/conformance/types/tuple/readonlyArraysAndTuples.ts(12,12): error TS1354: 'readonly' type modifier is only permitted on array and tuple literal types.
tests/cases/conformance/types/tuple/readonlyArraysAndTuples.ts(15,5): error TS2740: Type 'readonly string[]' is missing the following properties from type 'string[]': pop, push, reverse, shift, and 3 more.
tests/cases/conformance/types/tuple/readonlyArraysAndTuples.ts(17,5): error TS2740: Type 'readonly [string, string]' is missing the following properties from type 'string[]': pop, push, reverse, shift, and 3 more.
tests/cases/conformance/types/tuple/readonlyArraysAndTuples.ts(15,5): error TS4104: The type 'readonly string[]' is 'readonly' and cannot be assigned to the mutable type 'string[]'.
tests/cases/conformance/types/tuple/readonlyArraysAndTuples.ts(17,5): error TS4104: The type 'readonly [string, string]' is 'readonly' and cannot be assigned to the mutable type 'string[]'.
tests/cases/conformance/types/tuple/readonlyArraysAndTuples.ts(21,5): error TS2739: Type 'string[]' is missing the following properties from type '[string, string]': 0, 1
tests/cases/conformance/types/tuple/readonlyArraysAndTuples.ts(22,5): error TS2740: Type 'readonly string[]' is missing the following properties from type '[string, string]': 0, 1, pop, push, and 5 more.
tests/cases/conformance/types/tuple/readonlyArraysAndTuples.ts(23,5): error TS2740: Type 'readonly [string, string]' is missing the following properties from type '[string, string]': pop, push, reverse, shift, and 3 more.
tests/cases/conformance/types/tuple/readonlyArraysAndTuples.ts(23,5): error TS4104: The type 'readonly [string, string]' is 'readonly' and cannot be assigned to the mutable type '[string, string]'.
tests/cases/conformance/types/tuple/readonlyArraysAndTuples.ts(24,5): error TS2739: Type 'string[]' is missing the following properties from type 'readonly [string, string]': 0, 1
tests/cases/conformance/types/tuple/readonlyArraysAndTuples.ts(25,5): error TS2739: Type 'readonly string[]' is missing the following properties from type 'readonly [string, string]': 0, 1

Expand Down Expand Up @@ -36,11 +36,11 @@ tests/cases/conformance/types/tuple/readonlyArraysAndTuples.ts(25,5): error TS27
function f1(ma: string[], ra: readonly string[], mt: [string, string], rt: readonly [string, string]) {
ma = ra; // Error
~~
!!! error TS2740: Type 'readonly string[]' is missing the following properties from type 'string[]': pop, push, reverse, shift, and 3 more.
!!! error TS4104: The type 'readonly string[]' is 'readonly' and cannot be assigned to the mutable type 'string[]'.
ma = mt;
ma = rt; // Error
~~
!!! error TS2740: Type 'readonly [string, string]' is missing the following properties from type 'string[]': pop, push, reverse, shift, and 3 more.
!!! error TS4104: The type 'readonly [string, string]' is 'readonly' and cannot be assigned to the mutable type 'string[]'.
ra = ma;
ra = mt;
ra = rt;
Expand All @@ -52,7 +52,7 @@ tests/cases/conformance/types/tuple/readonlyArraysAndTuples.ts(25,5): error TS27
!!! error TS2740: Type 'readonly string[]' is missing the following properties from type '[string, string]': 0, 1, pop, push, and 5 more.
mt = rt; // Error
~~
!!! error TS2740: Type 'readonly [string, string]' is missing the following properties from type '[string, string]': pop, push, reverse, shift, and 3 more.
!!! error TS4104: The type 'readonly [string, string]' is 'readonly' and cannot be assigned to the mutable type '[string, string]'.
rt = ma; // Error
~~
!!! error TS2739: Type 'string[]' is missing the following properties from type 'readonly [string, string]': 0, 1
Expand Down
@@ -0,0 +1,58 @@
tests/cases/compiler/readonlyTupleAndArrayElaboration.ts(10,20): error TS2345: Argument of type 'readonly [3, 4]' is not assignable to parameter of type '[number, number]'.
The type 'readonly [3, 4]' is 'readonly' and cannot be assigned to the mutable type '[number, number]'.
tests/cases/compiler/readonlyTupleAndArrayElaboration.ts(13,8): error TS2345: Argument of type 'readonly [3, 4]' is not assignable to parameter of type 'number[]'.
The type 'readonly [3, 4]' is 'readonly' and cannot be assigned to the mutable type 'number[]'.
tests/cases/compiler/readonlyTupleAndArrayElaboration.ts(16,9): error TS2345: Argument of type 'readonly [3, 4]' is not assignable to parameter of type 'number[]'.
The type 'readonly [3, 4]' is 'readonly' and cannot be assigned to the mutable type 'number[]'.
tests/cases/compiler/readonlyTupleAndArrayElaboration.ts(22,9): error TS2345: Argument of type 'readonly number[]' is not assignable to parameter of type 'number[]'.
The type 'readonly number[]' is 'readonly' and cannot be assigned to the mutable type 'number[]'.
tests/cases/compiler/readonlyTupleAndArrayElaboration.ts(23,9): error TS2345: Argument of type 'readonly number[]' is not assignable to parameter of type 'number[]'.
The type 'readonly number[]' is 'readonly' and cannot be assigned to the mutable type 'number[]'.
tests/cases/compiler/readonlyTupleAndArrayElaboration.ts(24,9): error TS2345: Argument of type 'readonly number[]' is not assignable to parameter of type 'number[]'.
The type 'readonly number[]' is 'readonly' and cannot be assigned to the mutable type 'number[]'.


==== tests/cases/compiler/readonlyTupleAndArrayElaboration.ts (6 errors) ====
// @strict
// #Repro from #30839

let point = [3, 4] as const;

function distanceFromOrigin([x, y]: [number, number]) {
return Math.sqrt(x ** 2 + y ** 2);
}

distanceFromOrigin(point);
~~~~~
!!! error TS2345: Argument of type 'readonly [3, 4]' is not assignable to parameter of type '[number, number]'.
!!! error TS2345: The type 'readonly [3, 4]' is 'readonly' and cannot be assigned to the mutable type '[number, number]'.

declare function arryFn(x: number[]): void;
arryFn(point);
~~~~~
!!! error TS2345: Argument of type 'readonly [3, 4]' is not assignable to parameter of type 'number[]'.
!!! error TS2345: The type 'readonly [3, 4]' is 'readonly' and cannot be assigned to the mutable type 'number[]'.

declare function arryFn2(x: Array<number>): void;
arryFn2(point);
~~~~~
!!! error TS2345: Argument of type 'readonly [3, 4]' is not assignable to parameter of type 'number[]'.
!!! error TS2345: The type 'readonly [3, 4]' is 'readonly' and cannot be assigned to the mutable type 'number[]'.

declare const a: readonly number[];
declare const b: Readonly<number[]>;
declare const c: ReadonlyArray<number>;

arryFn2(a);
~
!!! error TS2345: Argument of type 'readonly number[]' is not assignable to parameter of type 'number[]'.
!!! error TS2345: The type 'readonly number[]' is 'readonly' and cannot be assigned to the mutable type 'number[]'.
arryFn2(b);
~
!!! error TS2345: Argument of type 'readonly number[]' is not assignable to parameter of type 'number[]'.
!!! error TS2345: The type 'readonly number[]' is 'readonly' and cannot be assigned to the mutable type 'number[]'.
arryFn2(c);
~
!!! error TS2345: Argument of type 'readonly number[]' is not assignable to parameter of type 'number[]'.
!!! error TS2345: The type 'readonly number[]' is 'readonly' and cannot be assigned to the mutable type 'number[]'.

41 changes: 41 additions & 0 deletions tests/baselines/reference/readonlyTupleAndArrayElaboration.js
@@ -0,0 +1,41 @@
//// [readonlyTupleAndArrayElaboration.ts]
// @strict
// #Repro from #30839

let point = [3, 4] as const;

function distanceFromOrigin([x, y]: [number, number]) {
return Math.sqrt(x ** 2 + y ** 2);
}

distanceFromOrigin(point);

declare function arryFn(x: number[]): void;
arryFn(point);

declare function arryFn2(x: Array<number>): void;
arryFn2(point);

declare const a: readonly number[];
declare const b: Readonly<number[]>;
declare const c: ReadonlyArray<number>;

arryFn2(a);
arryFn2(b);
arryFn2(c);


//// [readonlyTupleAndArrayElaboration.js]
// @strict
// #Repro from #30839
var point = [3, 4];
function distanceFromOrigin(_a) {
var x = _a[0], y = _a[1];
return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
}
distanceFromOrigin(point);
arryFn(point);
arryFn2(point);
arryFn2(a);
arryFn2(b);
arryFn2(c);