mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-06-10 18:04:18 -05:00
Correct tuple relations in --strictOptionalProperties mode (#44568)
* Fix relations for optional elements in tuples with --strictOptionalProperties * Accept new baselines * Add regression test * Address CR feedback
This commit is contained in:
@@ -15095,11 +15095,11 @@ namespace ts {
|
||||
}
|
||||
|
||||
function isTypicalNondistributiveConditional(root: ConditionalRoot) {
|
||||
return !root.isDistributive
|
||||
&& root.node.checkType.kind === SyntaxKind.TupleType
|
||||
&& length((root.node.checkType as TupleTypeNode).elements) === 1
|
||||
&& root.node.extendsType.kind === SyntaxKind.TupleType
|
||||
&& length((root.node.extendsType as TupleTypeNode).elements) === 1;
|
||||
return !root.isDistributive && isSingletonTupleType(root.node.checkType) && isSingletonTupleType(root.node.extendsType);
|
||||
}
|
||||
|
||||
function isSingletonTupleType(node: TypeNode) {
|
||||
return isTupleTypeNode(node) && length(node.elements) === 1 && !isOptionalTypeNode(node.elements[0]) && !isRestTypeNode(node.elements[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -18711,7 +18711,7 @@ namespace ts {
|
||||
return Ternary.False;
|
||||
}
|
||||
if (getObjectFlags(source) & ObjectFlags.Reference && getObjectFlags(target) & ObjectFlags.Reference && (source as TypeReference).target === (target as TypeReference).target &&
|
||||
!(getObjectFlags(source) & ObjectFlags.MarkerType || getObjectFlags(target) & ObjectFlags.MarkerType)) {
|
||||
!isTupleType(source) && !(getObjectFlags(source) & ObjectFlags.MarkerType || getObjectFlags(target) & ObjectFlags.MarkerType)) {
|
||||
// We have type references to the same generic type, and the type references are not marker
|
||||
// type references (which are intended by be compared structurally). Obtain the variance
|
||||
// information for the type parameters and relate the type arguments accordingly.
|
||||
@@ -19182,7 +19182,7 @@ namespace ts {
|
||||
removeMissingType(targetType, !!(targetFlags & ElementFlags.Optional));
|
||||
const related = isRelatedTo(sourceType, targetCheckType, reportErrors, /*headMessage*/ undefined, intersectionState);
|
||||
if (!related) {
|
||||
if (reportErrors) {
|
||||
if (reportErrors && (targetArity > 1 || sourceArity > 1)) {
|
||||
if (i < startCount || i >= targetArity - endCount || sourceArity - startCount - endCount === 1) {
|
||||
reportIncompatibleError(Diagnostics.Type_at_position_0_in_source_is_not_compatible_with_type_at_position_1_in_target, sourceIndex, i);
|
||||
}
|
||||
|
||||
@@ -21,7 +21,8 @@ tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(28,5): error
|
||||
Type '2' is not assignable to type '1'.
|
||||
tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(29,5): error TS2322: Type '{ 0: string; 1: number; length: 2; }' is not assignable to type '[string]'.
|
||||
tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(30,5): error TS2322: Type '[string, number]' is not assignable to type '[number, string]'.
|
||||
Type 'string' is not assignable to type 'number'.
|
||||
Type at position 0 in source is not compatible with type at position 0 in target.
|
||||
Type 'string' is not assignable to type 'number'.
|
||||
tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(31,5): error TS2322: Type 'StrNum' is not assignable to type '[number, string]'.
|
||||
Types of property '0' are incompatible.
|
||||
Type 'string' is not assignable to type 'number'.
|
||||
@@ -97,7 +98,8 @@ tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(32,5): error
|
||||
var n1: [number, string] = x;
|
||||
~~
|
||||
!!! error TS2322: Type '[string, number]' is not assignable to type '[number, string]'.
|
||||
!!! error TS2322: Type 'string' is not assignable to type 'number'.
|
||||
!!! error TS2322: Type at position 0 in source is not compatible with type at position 0 in target.
|
||||
!!! error TS2322: Type 'string' is not assignable to type 'number'.
|
||||
var n2: [number, string] = y;
|
||||
~~
|
||||
!!! error TS2322: Type 'StrNum' is not assignable to type '[number, string]'.
|
||||
|
||||
@@ -7,9 +7,11 @@ tests/cases/conformance/types/tuple/castingTuple.ts(18,21): error TS2352: Conver
|
||||
Source has 2 element(s) but target requires 3.
|
||||
tests/cases/conformance/types/tuple/castingTuple.ts(20,33): error TS2493: Tuple type '[C, D, A]' of length '3' has no element at index '5'.
|
||||
tests/cases/conformance/types/tuple/castingTuple.ts(30,10): error TS2352: Conversion of type '[number, string]' to type '[number, number]' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
|
||||
Type 'string' is not comparable to type 'number'.
|
||||
Type at position 1 in source is not compatible with type at position 1 in target.
|
||||
Type 'string' is not comparable to type 'number'.
|
||||
tests/cases/conformance/types/tuple/castingTuple.ts(31,10): error TS2352: Conversion of type '[C, D]' to type '[A, I]' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
|
||||
Property 'a' is missing in type 'C' but required in type 'A'.
|
||||
Type at position 0 in source is not compatible with type at position 0 in target.
|
||||
Property 'a' is missing in type 'C' but required in type 'A'.
|
||||
tests/cases/conformance/types/tuple/castingTuple.ts(32,5): error TS2403: Subsequent variable declarations must have the same type. Variable 'array1' must be of type '{}[]', but here has type 'number[]'.
|
||||
tests/cases/conformance/types/tuple/castingTuple.ts(33,1): error TS2304: Cannot find name 't4'.
|
||||
|
||||
@@ -60,11 +62,13 @@ tests/cases/conformance/types/tuple/castingTuple.ts(33,1): error TS2304: Cannot
|
||||
var t3 = <[number, number]>numStrTuple;
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2352: Conversion of type '[number, string]' to type '[number, number]' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
|
||||
!!! error TS2352: Type 'string' is not comparable to type 'number'.
|
||||
!!! error TS2352: Type at position 1 in source is not compatible with type at position 1 in target.
|
||||
!!! error TS2352: Type 'string' is not comparable to type 'number'.
|
||||
var t9 = <[A, I]>classCDTuple;
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2352: Conversion of type '[C, D]' to type '[A, I]' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
|
||||
!!! error TS2352: Property 'a' is missing in type 'C' but required in type 'A'.
|
||||
!!! error TS2352: Type at position 0 in source is not compatible with type at position 0 in target.
|
||||
!!! error TS2352: Property 'a' is missing in type 'C' but required in type 'A'.
|
||||
!!! related TS2728 tests/cases/conformance/types/tuple/castingTuple.ts:2:11: 'a' is declared here.
|
||||
var array1 = <number[]>numStrTuple;
|
||||
~~~~~~
|
||||
|
||||
@@ -12,8 +12,9 @@ tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(23,1): error TS23
|
||||
tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(24,1): error TS2322: Type '[C, string | number]' is not assignable to type '[C, string | number, D]'.
|
||||
Source has 2 element(s) but target requires 3.
|
||||
tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(25,1): error TS2322: Type '[number, string | number]' is not assignable to type '[number, string]'.
|
||||
Type 'string | number' is not assignable to type 'string'.
|
||||
Type 'number' is not assignable to type 'string'.
|
||||
Type at position 1 in source is not compatible with type at position 1 in target.
|
||||
Type 'string | number' is not assignable to type 'string'.
|
||||
Type 'number' is not assignable to type 'string'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts (8 errors) ====
|
||||
@@ -65,5 +66,6 @@ tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(25,1): error TS23
|
||||
numStrTuple = unionTuple3;
|
||||
~~~~~~~~~~~
|
||||
!!! error TS2322: Type '[number, string | number]' is not assignable to type '[number, string]'.
|
||||
!!! error TS2322: Type 'string | number' is not assignable to type 'string'.
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
!!! error TS2322: Type at position 1 in source is not compatible with type at position 1 in target.
|
||||
!!! error TS2322: Type 'string | number' is not assignable to type 'string'.
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
@@ -1,5 +1,6 @@
|
||||
tests/cases/conformance/es6/destructuring/iterableArrayPattern29.ts(2,21): error TS2345: Argument of type '[string, boolean]' is not assignable to parameter of type '[string, number]'.
|
||||
Type 'boolean' is not assignable to type 'number'.
|
||||
Type at position 1 in source is not compatible with type at position 1 in target.
|
||||
Type 'boolean' is not assignable to type 'number'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/es6/destructuring/iterableArrayPattern29.ts (1 errors) ====
|
||||
@@ -7,4 +8,5 @@ tests/cases/conformance/es6/destructuring/iterableArrayPattern29.ts(2,21): error
|
||||
takeFirstTwoEntries(...new Map([["", true], ["hello", true]]));
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2345: Argument of type '[string, boolean]' is not assignable to parameter of type '[string, number]'.
|
||||
!!! error TS2345: Type 'boolean' is not assignable to type 'number'.
|
||||
!!! error TS2345: Type at position 1 in source is not compatible with type at position 1 in target.
|
||||
!!! error TS2345: Type 'boolean' is not assignable to type 'number'.
|
||||
@@ -11,9 +11,11 @@ tests/cases/conformance/types/tuple/restTupleElements1.ts(29,18): error TS2344:
|
||||
tests/cases/conformance/types/tuple/restTupleElements1.ts(30,18): error TS2344: Type '[number, ...number[]]' does not satisfy the constraint '[number]'.
|
||||
Target allows only 1 element(s) but source may have more.
|
||||
tests/cases/conformance/types/tuple/restTupleElements1.ts(32,31): error TS2344: Type '[number, ...string[]]' does not satisfy the constraint '[number, ...number[]]'.
|
||||
Type 'string' is not assignable to type 'number'.
|
||||
Type at position 1 in source is not compatible with type at position 1 in target.
|
||||
Type 'string' is not assignable to type 'number'.
|
||||
tests/cases/conformance/types/tuple/restTupleElements1.ts(33,31): error TS2344: Type '[string, ...number[]]' does not satisfy the constraint '[number, ...number[]]'.
|
||||
Type 'string' is not assignable to type 'number'.
|
||||
Type at position 0 in source is not compatible with type at position 0 in target.
|
||||
Type 'string' is not assignable to type 'number'.
|
||||
tests/cases/conformance/types/tuple/restTupleElements1.ts(34,31): error TS2344: Type '[number, number, string]' does not satisfy the constraint '[number, ...number[]]'.
|
||||
Type at positions 1 through 2 in source is not compatible with type at position 1 in target.
|
||||
Type 'string | number' is not assignable to type 'number'.
|
||||
@@ -81,11 +83,13 @@ tests/cases/conformance/types/tuple/restTupleElements1.ts(59,4): error TS2345: A
|
||||
assign<[number, ...number[]], [number, ...string[]]>(); // Error
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2344: Type '[number, ...string[]]' does not satisfy the constraint '[number, ...number[]]'.
|
||||
!!! error TS2344: Type 'string' is not assignable to type 'number'.
|
||||
!!! error TS2344: Type at position 1 in source is not compatible with type at position 1 in target.
|
||||
!!! error TS2344: Type 'string' is not assignable to type 'number'.
|
||||
assign<[number, ...number[]], [string, ...number[]]>(); // Error
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2344: Type '[string, ...number[]]' does not satisfy the constraint '[number, ...number[]]'.
|
||||
!!! error TS2344: Type 'string' is not assignable to type 'number'.
|
||||
!!! error TS2344: Type at position 0 in source is not compatible with type at position 0 in target.
|
||||
!!! error TS2344: Type 'string' is not assignable to type 'number'.
|
||||
assign<[number, ...number[]], [number, number, string]>(); // Error
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2344: Type '[number, number, string]' does not satisfy the constraint '[number, ...number[]]'.
|
||||
|
||||
19
tests/baselines/reference/strictOptionalProperties2.js
Normal file
19
tests/baselines/reference/strictOptionalProperties2.js
Normal file
@@ -0,0 +1,19 @@
|
||||
//// [strictOptionalProperties2.ts]
|
||||
// Repro from #44567
|
||||
|
||||
type T1 = { 0?: string | undefined } extends { 0?: string } ? true : false; // false
|
||||
type T2 = [(string | undefined)?] extends [string?] ? true : false; // false
|
||||
|
||||
|
||||
//// [strictOptionalProperties2.js]
|
||||
"use strict";
|
||||
// Repro from #44567
|
||||
|
||||
|
||||
//// [strictOptionalProperties2.d.ts]
|
||||
declare type T1 = {
|
||||
0?: string | undefined;
|
||||
} extends {
|
||||
0?: string;
|
||||
} ? true : false;
|
||||
declare type T2 = [(string | undefined)?] extends [string?] ? true : false;
|
||||
11
tests/baselines/reference/strictOptionalProperties2.symbols
Normal file
11
tests/baselines/reference/strictOptionalProperties2.symbols
Normal file
@@ -0,0 +1,11 @@
|
||||
=== tests/cases/compiler/strictOptionalProperties2.ts ===
|
||||
// Repro from #44567
|
||||
|
||||
type T1 = { 0?: string | undefined } extends { 0?: string } ? true : false; // false
|
||||
>T1 : Symbol(T1, Decl(strictOptionalProperties2.ts, 0, 0))
|
||||
>0 : Symbol(0, Decl(strictOptionalProperties2.ts, 2, 11))
|
||||
>0 : Symbol(0, Decl(strictOptionalProperties2.ts, 2, 46))
|
||||
|
||||
type T2 = [(string | undefined)?] extends [string?] ? true : false; // false
|
||||
>T2 : Symbol(T2, Decl(strictOptionalProperties2.ts, 2, 75))
|
||||
|
||||
15
tests/baselines/reference/strictOptionalProperties2.types
Normal file
15
tests/baselines/reference/strictOptionalProperties2.types
Normal file
@@ -0,0 +1,15 @@
|
||||
=== tests/cases/compiler/strictOptionalProperties2.ts ===
|
||||
// Repro from #44567
|
||||
|
||||
type T1 = { 0?: string | undefined } extends { 0?: string } ? true : false; // false
|
||||
>T1 : false
|
||||
>0 : string | undefined
|
||||
>0 : string | undefined
|
||||
>true : true
|
||||
>false : false
|
||||
|
||||
type T2 = [(string | undefined)?] extends [string?] ? true : false; // false
|
||||
>T2 : false
|
||||
>true : true
|
||||
>false : false
|
||||
|
||||
@@ -18,9 +18,11 @@ tests/cases/compiler/tupleTypes.ts(49,1): error TS2322: Type '[number, {}]' is n
|
||||
Type 'number | {}' is not assignable to type 'number'.
|
||||
Type '{}' is not assignable to type 'number'.
|
||||
tests/cases/compiler/tupleTypes.ts(50,1): error TS2322: Type '[number, number]' is not assignable to type '[number, string]'.
|
||||
Type 'number' is not assignable to type 'string'.
|
||||
Type at position 1 in source is not compatible with type at position 1 in target.
|
||||
Type 'number' is not assignable to type 'string'.
|
||||
tests/cases/compiler/tupleTypes.ts(51,1): error TS2322: Type '[number, {}]' is not assignable to type '[number, string]'.
|
||||
Type '{}' is not assignable to type 'string'.
|
||||
Type at position 1 in source is not compatible with type at position 1 in target.
|
||||
Type '{}' is not assignable to type 'string'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/tupleTypes.ts (14 errors) ====
|
||||
@@ -109,11 +111,13 @@ tests/cases/compiler/tupleTypes.ts(51,1): error TS2322: Type '[number, {}]' is n
|
||||
a1 = a2; // Error
|
||||
~~
|
||||
!!! error TS2322: Type '[number, number]' is not assignable to type '[number, string]'.
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
!!! error TS2322: Type at position 1 in source is not compatible with type at position 1 in target.
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
a1 = a3; // Error
|
||||
~~
|
||||
!!! error TS2322: Type '[number, {}]' is not assignable to type '[number, string]'.
|
||||
!!! error TS2322: Type '{}' is not assignable to type 'string'.
|
||||
!!! error TS2322: Type at position 1 in source is not compatible with type at position 1 in target.
|
||||
!!! error TS2322: Type '{}' is not assignable to type 'string'.
|
||||
a3 = a1;
|
||||
a3 = a2;
|
||||
|
||||
@@ -9,8 +9,9 @@ tests/cases/conformance/types/tuple/variadicTuples1.ts(149,5): error TS2322: Typ
|
||||
tests/cases/conformance/types/tuple/variadicTuples1.ts(151,5): error TS2322: Type '[string, ...unknown[]]' is not assignable to type '[string, ...U]'.
|
||||
Target requires 2 element(s) but source may have fewer.
|
||||
tests/cases/conformance/types/tuple/variadicTuples1.ts(152,5): error TS2322: Type '[string, ...T]' is not assignable to type '[string, ...U]'.
|
||||
Type 'T' is not assignable to type 'U'.
|
||||
'T' is assignable to the constraint of type 'U', but 'U' could be instantiated with a different subtype of constraint 'string[]'.
|
||||
Type at position 1 in source is not compatible with type at position 1 in target.
|
||||
Type 'T' is not assignable to type 'U'.
|
||||
'T' is assignable to the constraint of type 'U', but 'U' could be instantiated with a different subtype of constraint 'string[]'.
|
||||
tests/cases/conformance/types/tuple/variadicTuples1.ts(160,5): error TS2322: Type 'readonly [...T]' is not assignable to type 'T'.
|
||||
'T' could be instantiated with an arbitrary type which could be unrelated to 'readonly [...T]'.
|
||||
tests/cases/conformance/types/tuple/variadicTuples1.ts(162,5): error TS4104: The type 'readonly [...T]' is 'readonly' and cannot be assigned to the mutable type '[...T]'.
|
||||
@@ -212,8 +213,9 @@ tests/cases/conformance/types/tuple/variadicTuples1.ts(397,7): error TS2322: Typ
|
||||
z = y; // Error
|
||||
~
|
||||
!!! error TS2322: Type '[string, ...T]' is not assignable to type '[string, ...U]'.
|
||||
!!! error TS2322: Type 'T' is not assignable to type 'U'.
|
||||
!!! error TS2322: 'T' is assignable to the constraint of type 'U', but 'U' could be instantiated with a different subtype of constraint 'string[]'.
|
||||
!!! error TS2322: Type at position 1 in source is not compatible with type at position 1 in target.
|
||||
!!! error TS2322: Type 'T' is not assignable to type 'U'.
|
||||
!!! error TS2322: 'T' is assignable to the constraint of type 'U', but 'U' could be instantiated with a different subtype of constraint 'string[]'.
|
||||
}
|
||||
|
||||
// For a generic type T, [...T] is assignable to T, T is assignable to readonly [...T], and T is assignable
|
||||
|
||||
7
tests/cases/compiler/strictOptionalProperties2.ts
Normal file
7
tests/cases/compiler/strictOptionalProperties2.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
// @strict: true
|
||||
// @declaration: true
|
||||
|
||||
// Repro from #44567
|
||||
|
||||
type T1 = { 0?: string | undefined } extends { 0?: string } ? true : false; // false
|
||||
type T2 = [(string | undefined)?] extends [string?] ? true : false; // false
|
||||
Reference in New Issue
Block a user