Skip to content

Commit 01054e0

Browse files
authoredSep 21, 2022
Consistently add undefined/missing to optional tuple element types (#50831)
* Consistently add undefined/missing type to optional tuple elements * Accept new baselines * Add regression test
1 parent d90795e commit 01054e0

7 files changed

+148
-4
lines changed
 

‎src/compiler/checker.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -14660,7 +14660,7 @@ namespace ts {
1466014660
if (flags & (ElementFlags.Optional | ElementFlags.Rest)) {
1466114661
lastOptionalOrRestIndex = expandedFlags.length;
1466214662
}
14663-
expandedTypes.push(type);
14663+
expandedTypes.push(flags & ElementFlags.Optional ? addOptionality(type, /*isProperty*/ true) : type);
1466414664
expandedFlags.push(flags);
1466514665
if (expandedDeclarations && declaration) {
1466614666
expandedDeclarations.push(declaration);
@@ -21705,7 +21705,8 @@ namespace ts {
2170521705

2170621706
function getOptionalType(type: Type, isProperty = false): Type {
2170721707
Debug.assert(strictNullChecks);
21708-
return type.flags & TypeFlags.Undefined ? type : getUnionType([type, isProperty ? missingType : undefinedType]);
21708+
const missingOrUndefined = isProperty ? missingType : undefinedType;
21709+
return type.flags & TypeFlags.Undefined || type.flags & TypeFlags.Union && (type as UnionType).types[0] === missingOrUndefined ? type : getUnionType([type, missingOrUndefined]);
2170921710
}
2171021711

2171121712
function getGlobalNonNullableTypeInstantiation(type: Type) {

‎tests/baselines/reference/mappedTypesArraysTuples.types

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ type Boxified<T> = { [P in keyof T]: Box<T[P]> };
77
>Boxified : Boxified<T>
88

99
type T00 = Boxified<[number, string?, ...boolean[]]>;
10-
>T00 : [Box<number>, Box<string | undefined>?, ...Box<boolean>[]]
10+
>T00 : [Box<number>, (Box<string | undefined> | undefined)?, ...Box<boolean>[]]
1111

1212
type T01 = Partial<[number, string?, ...boolean[]]>;
1313
>T01 : [(number | undefined)?, (string | undefined)?, ...(boolean | undefined)[]]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//// [optionalTupleElementsAndUndefined.ts]
2+
// Repro from #50753
3+
4+
type UnNullify<T> = { [K in keyof T]: NonNullable<T[K]> };
5+
6+
type Foo = UnNullify<[a: 1, b?: 2 | undefined]>;
7+
8+
type Test = [a: 1, b?: 2] extends Foo ? true : false; // true
9+
10+
// Types in the following declarations should be identical
11+
12+
var v: [1, 2?];
13+
var v: [1, (2 | undefined)?];
14+
var v: [a: 1, b?: 2];
15+
var v: [a: 1, b?: 2 | undefined];
16+
var v: UnNullify<[1, 2?]>;
17+
var v: UnNullify<[1, (2 | undefined)?]>;
18+
var v: UnNullify<[a: 1, b?: 2]>;
19+
var v: UnNullify<[a: 1, b?: 2 | undefined]>;
20+
21+
22+
//// [optionalTupleElementsAndUndefined.js]
23+
"use strict";
24+
// Repro from #50753
25+
// Types in the following declarations should be identical
26+
var v;
27+
var v;
28+
var v;
29+
var v;
30+
var v;
31+
var v;
32+
var v;
33+
var v;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
=== tests/cases/compiler/optionalTupleElementsAndUndefined.ts ===
2+
// Repro from #50753
3+
4+
type UnNullify<T> = { [K in keyof T]: NonNullable<T[K]> };
5+
>UnNullify : Symbol(UnNullify, Decl(optionalTupleElementsAndUndefined.ts, 0, 0))
6+
>T : Symbol(T, Decl(optionalTupleElementsAndUndefined.ts, 2, 15))
7+
>K : Symbol(K, Decl(optionalTupleElementsAndUndefined.ts, 2, 23))
8+
>T : Symbol(T, Decl(optionalTupleElementsAndUndefined.ts, 2, 15))
9+
>NonNullable : Symbol(NonNullable, Decl(lib.es5.d.ts, --, --))
10+
>T : Symbol(T, Decl(optionalTupleElementsAndUndefined.ts, 2, 15))
11+
>K : Symbol(K, Decl(optionalTupleElementsAndUndefined.ts, 2, 23))
12+
13+
type Foo = UnNullify<[a: 1, b?: 2 | undefined]>;
14+
>Foo : Symbol(Foo, Decl(optionalTupleElementsAndUndefined.ts, 2, 58))
15+
>UnNullify : Symbol(UnNullify, Decl(optionalTupleElementsAndUndefined.ts, 0, 0))
16+
17+
type Test = [a: 1, b?: 2] extends Foo ? true : false; // true
18+
>Test : Symbol(Test, Decl(optionalTupleElementsAndUndefined.ts, 4, 48))
19+
>Foo : Symbol(Foo, Decl(optionalTupleElementsAndUndefined.ts, 2, 58))
20+
21+
// Types in the following declarations should be identical
22+
23+
var v: [1, 2?];
24+
>v : Symbol(v, Decl(optionalTupleElementsAndUndefined.ts, 10, 3), Decl(optionalTupleElementsAndUndefined.ts, 11, 3), Decl(optionalTupleElementsAndUndefined.ts, 12, 3), Decl(optionalTupleElementsAndUndefined.ts, 13, 3), Decl(optionalTupleElementsAndUndefined.ts, 14, 3) ... and 3 more)
25+
26+
var v: [1, (2 | undefined)?];
27+
>v : Symbol(v, Decl(optionalTupleElementsAndUndefined.ts, 10, 3), Decl(optionalTupleElementsAndUndefined.ts, 11, 3), Decl(optionalTupleElementsAndUndefined.ts, 12, 3), Decl(optionalTupleElementsAndUndefined.ts, 13, 3), Decl(optionalTupleElementsAndUndefined.ts, 14, 3) ... and 3 more)
28+
29+
var v: [a: 1, b?: 2];
30+
>v : Symbol(v, Decl(optionalTupleElementsAndUndefined.ts, 10, 3), Decl(optionalTupleElementsAndUndefined.ts, 11, 3), Decl(optionalTupleElementsAndUndefined.ts, 12, 3), Decl(optionalTupleElementsAndUndefined.ts, 13, 3), Decl(optionalTupleElementsAndUndefined.ts, 14, 3) ... and 3 more)
31+
32+
var v: [a: 1, b?: 2 | undefined];
33+
>v : Symbol(v, Decl(optionalTupleElementsAndUndefined.ts, 10, 3), Decl(optionalTupleElementsAndUndefined.ts, 11, 3), Decl(optionalTupleElementsAndUndefined.ts, 12, 3), Decl(optionalTupleElementsAndUndefined.ts, 13, 3), Decl(optionalTupleElementsAndUndefined.ts, 14, 3) ... and 3 more)
34+
35+
var v: UnNullify<[1, 2?]>;
36+
>v : Symbol(v, Decl(optionalTupleElementsAndUndefined.ts, 10, 3), Decl(optionalTupleElementsAndUndefined.ts, 11, 3), Decl(optionalTupleElementsAndUndefined.ts, 12, 3), Decl(optionalTupleElementsAndUndefined.ts, 13, 3), Decl(optionalTupleElementsAndUndefined.ts, 14, 3) ... and 3 more)
37+
>UnNullify : Symbol(UnNullify, Decl(optionalTupleElementsAndUndefined.ts, 0, 0))
38+
39+
var v: UnNullify<[1, (2 | undefined)?]>;
40+
>v : Symbol(v, Decl(optionalTupleElementsAndUndefined.ts, 10, 3), Decl(optionalTupleElementsAndUndefined.ts, 11, 3), Decl(optionalTupleElementsAndUndefined.ts, 12, 3), Decl(optionalTupleElementsAndUndefined.ts, 13, 3), Decl(optionalTupleElementsAndUndefined.ts, 14, 3) ... and 3 more)
41+
>UnNullify : Symbol(UnNullify, Decl(optionalTupleElementsAndUndefined.ts, 0, 0))
42+
43+
var v: UnNullify<[a: 1, b?: 2]>;
44+
>v : Symbol(v, Decl(optionalTupleElementsAndUndefined.ts, 10, 3), Decl(optionalTupleElementsAndUndefined.ts, 11, 3), Decl(optionalTupleElementsAndUndefined.ts, 12, 3), Decl(optionalTupleElementsAndUndefined.ts, 13, 3), Decl(optionalTupleElementsAndUndefined.ts, 14, 3) ... and 3 more)
45+
>UnNullify : Symbol(UnNullify, Decl(optionalTupleElementsAndUndefined.ts, 0, 0))
46+
47+
var v: UnNullify<[a: 1, b?: 2 | undefined]>;
48+
>v : Symbol(v, Decl(optionalTupleElementsAndUndefined.ts, 10, 3), Decl(optionalTupleElementsAndUndefined.ts, 11, 3), Decl(optionalTupleElementsAndUndefined.ts, 12, 3), Decl(optionalTupleElementsAndUndefined.ts, 13, 3), Decl(optionalTupleElementsAndUndefined.ts, 14, 3) ... and 3 more)
49+
>UnNullify : Symbol(UnNullify, Decl(optionalTupleElementsAndUndefined.ts, 0, 0))
50+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
=== tests/cases/compiler/optionalTupleElementsAndUndefined.ts ===
2+
// Repro from #50753
3+
4+
type UnNullify<T> = { [K in keyof T]: NonNullable<T[K]> };
5+
>UnNullify : UnNullify<T>
6+
7+
type Foo = UnNullify<[a: 1, b?: 2 | undefined]>;
8+
>Foo : [a: 1, b?: 2 | undefined]
9+
10+
type Test = [a: 1, b?: 2] extends Foo ? true : false; // true
11+
>Test : true
12+
>true : true
13+
>false : false
14+
15+
// Types in the following declarations should be identical
16+
17+
var v: [1, 2?];
18+
>v : [1, (2 | undefined)?]
19+
20+
var v: [1, (2 | undefined)?];
21+
>v : [1, (2 | undefined)?]
22+
23+
var v: [a: 1, b?: 2];
24+
>v : [1, (2 | undefined)?]
25+
26+
var v: [a: 1, b?: 2 | undefined];
27+
>v : [1, (2 | undefined)?]
28+
29+
var v: UnNullify<[1, 2?]>;
30+
>v : [1, (2 | undefined)?]
31+
32+
var v: UnNullify<[1, (2 | undefined)?]>;
33+
>v : [1, (2 | undefined)?]
34+
35+
var v: UnNullify<[a: 1, b?: 2]>;
36+
>v : [1, (2 | undefined)?]
37+
38+
var v: UnNullify<[a: 1, b?: 2 | undefined]>;
39+
>v : [1, (2 | undefined)?]
40+

‎tests/baselines/reference/variadicTuples1.types

+1-1
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,7 @@ type Arrayify<T> = { [P in keyof T]: T[P][] };
409409
>Arrayify : Arrayify<T>
410410

411411
type TM1<U extends unknown[]> = Arrayify<readonly [string, number?, ...U, ...boolean[]]>; // [string[], (number | undefined)[]?, Arrayify<U>, ...boolean[][]]
412-
>TM1 : readonly [string[], (number | undefined)[]?, ...Arrayify<U>, ...boolean[][]]
412+
>TM1 : readonly [string[], ((number | undefined)[] | undefined)?, ...Arrayify<U>, ...boolean[][]]
413413

414414
type TP1<T extends unknown[]> = Partial<[string, ...T, number]>; // [string?, Partial<T>, number?]
415415
>TP1 : [(string | undefined)?, ...Partial<T>, (number | undefined)?]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// @strict: true
2+
3+
// Repro from #50753
4+
5+
type UnNullify<T> = { [K in keyof T]: NonNullable<T[K]> };
6+
7+
type Foo = UnNullify<[a: 1, b?: 2 | undefined]>;
8+
9+
type Test = [a: 1, b?: 2] extends Foo ? true : false; // true
10+
11+
// Types in the following declarations should be identical
12+
13+
var v: [1, 2?];
14+
var v: [1, (2 | undefined)?];
15+
var v: [a: 1, b?: 2];
16+
var v: [a: 1, b?: 2 | undefined];
17+
var v: UnNullify<[1, 2?]>;
18+
var v: UnNullify<[1, (2 | undefined)?]>;
19+
var v: UnNullify<[a: 1, b?: 2]>;
20+
var v: UnNullify<[a: 1, b?: 2 | undefined]>;

0 commit comments

Comments
 (0)
Please sign in to comment.