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
This commit is contained in:
Anders Hejlsberg 2022-09-20 18:14:20 -07:00 committed by GitHub
parent d90795e799
commit 01054e05ab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 148 additions and 4 deletions

View File

@ -14660,7 +14660,7 @@ namespace ts {
if (flags & (ElementFlags.Optional | ElementFlags.Rest)) {
lastOptionalOrRestIndex = expandedFlags.length;
}
expandedTypes.push(type);
expandedTypes.push(flags & ElementFlags.Optional ? addOptionality(type, /*isProperty*/ true) : type);
expandedFlags.push(flags);
if (expandedDeclarations && declaration) {
expandedDeclarations.push(declaration);
@ -21705,7 +21705,8 @@ namespace ts {
function getOptionalType(type: Type, isProperty = false): Type {
Debug.assert(strictNullChecks);
return type.flags & TypeFlags.Undefined ? type : getUnionType([type, isProperty ? missingType : undefinedType]);
const missingOrUndefined = isProperty ? missingType : undefinedType;
return type.flags & TypeFlags.Undefined || type.flags & TypeFlags.Union && (type as UnionType).types[0] === missingOrUndefined ? type : getUnionType([type, missingOrUndefined]);
}
function getGlobalNonNullableTypeInstantiation(type: Type) {

View File

@ -7,7 +7,7 @@ type Boxified<T> = { [P in keyof T]: Box<T[P]> };
>Boxified : Boxified<T>
type T00 = Boxified<[number, string?, ...boolean[]]>;
>T00 : [Box<number>, Box<string | undefined>?, ...Box<boolean>[]]
>T00 : [Box<number>, (Box<string | undefined> | undefined)?, ...Box<boolean>[]]
type T01 = Partial<[number, string?, ...boolean[]]>;
>T01 : [(number | undefined)?, (string | undefined)?, ...(boolean | undefined)[]]

View File

@ -0,0 +1,33 @@
//// [optionalTupleElementsAndUndefined.ts]
// Repro from #50753
type UnNullify<T> = { [K in keyof T]: NonNullable<T[K]> };
type Foo = UnNullify<[a: 1, b?: 2 | undefined]>;
type Test = [a: 1, b?: 2] extends Foo ? true : false; // true
// Types in the following declarations should be identical
var v: [1, 2?];
var v: [1, (2 | undefined)?];
var v: [a: 1, b?: 2];
var v: [a: 1, b?: 2 | undefined];
var v: UnNullify<[1, 2?]>;
var v: UnNullify<[1, (2 | undefined)?]>;
var v: UnNullify<[a: 1, b?: 2]>;
var v: UnNullify<[a: 1, b?: 2 | undefined]>;
//// [optionalTupleElementsAndUndefined.js]
"use strict";
// Repro from #50753
// Types in the following declarations should be identical
var v;
var v;
var v;
var v;
var v;
var v;
var v;
var v;

View File

@ -0,0 +1,50 @@
=== tests/cases/compiler/optionalTupleElementsAndUndefined.ts ===
// Repro from #50753
type UnNullify<T> = { [K in keyof T]: NonNullable<T[K]> };
>UnNullify : Symbol(UnNullify, Decl(optionalTupleElementsAndUndefined.ts, 0, 0))
>T : Symbol(T, Decl(optionalTupleElementsAndUndefined.ts, 2, 15))
>K : Symbol(K, Decl(optionalTupleElementsAndUndefined.ts, 2, 23))
>T : Symbol(T, Decl(optionalTupleElementsAndUndefined.ts, 2, 15))
>NonNullable : Symbol(NonNullable, Decl(lib.es5.d.ts, --, --))
>T : Symbol(T, Decl(optionalTupleElementsAndUndefined.ts, 2, 15))
>K : Symbol(K, Decl(optionalTupleElementsAndUndefined.ts, 2, 23))
type Foo = UnNullify<[a: 1, b?: 2 | undefined]>;
>Foo : Symbol(Foo, Decl(optionalTupleElementsAndUndefined.ts, 2, 58))
>UnNullify : Symbol(UnNullify, Decl(optionalTupleElementsAndUndefined.ts, 0, 0))
type Test = [a: 1, b?: 2] extends Foo ? true : false; // true
>Test : Symbol(Test, Decl(optionalTupleElementsAndUndefined.ts, 4, 48))
>Foo : Symbol(Foo, Decl(optionalTupleElementsAndUndefined.ts, 2, 58))
// Types in the following declarations should be identical
var v: [1, 2?];
>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)
var v: [1, (2 | undefined)?];
>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)
var v: [a: 1, b?: 2];
>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)
var v: [a: 1, b?: 2 | undefined];
>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)
var v: UnNullify<[1, 2?]>;
>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)
>UnNullify : Symbol(UnNullify, Decl(optionalTupleElementsAndUndefined.ts, 0, 0))
var v: UnNullify<[1, (2 | undefined)?]>;
>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)
>UnNullify : Symbol(UnNullify, Decl(optionalTupleElementsAndUndefined.ts, 0, 0))
var v: UnNullify<[a: 1, b?: 2]>;
>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)
>UnNullify : Symbol(UnNullify, Decl(optionalTupleElementsAndUndefined.ts, 0, 0))
var v: UnNullify<[a: 1, b?: 2 | undefined]>;
>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)
>UnNullify : Symbol(UnNullify, Decl(optionalTupleElementsAndUndefined.ts, 0, 0))

View File

@ -0,0 +1,40 @@
=== tests/cases/compiler/optionalTupleElementsAndUndefined.ts ===
// Repro from #50753
type UnNullify<T> = { [K in keyof T]: NonNullable<T[K]> };
>UnNullify : UnNullify<T>
type Foo = UnNullify<[a: 1, b?: 2 | undefined]>;
>Foo : [a: 1, b?: 2 | undefined]
type Test = [a: 1, b?: 2] extends Foo ? true : false; // true
>Test : true
>true : true
>false : false
// Types in the following declarations should be identical
var v: [1, 2?];
>v : [1, (2 | undefined)?]
var v: [1, (2 | undefined)?];
>v : [1, (2 | undefined)?]
var v: [a: 1, b?: 2];
>v : [1, (2 | undefined)?]
var v: [a: 1, b?: 2 | undefined];
>v : [1, (2 | undefined)?]
var v: UnNullify<[1, 2?]>;
>v : [1, (2 | undefined)?]
var v: UnNullify<[1, (2 | undefined)?]>;
>v : [1, (2 | undefined)?]
var v: UnNullify<[a: 1, b?: 2]>;
>v : [1, (2 | undefined)?]
var v: UnNullify<[a: 1, b?: 2 | undefined]>;
>v : [1, (2 | undefined)?]

View File

@ -409,7 +409,7 @@ type Arrayify<T> = { [P in keyof T]: T[P][] };
>Arrayify : Arrayify<T>
type TM1<U extends unknown[]> = Arrayify<readonly [string, number?, ...U, ...boolean[]]>; // [string[], (number | undefined)[]?, Arrayify<U>, ...boolean[][]]
>TM1 : readonly [string[], (number | undefined)[]?, ...Arrayify<U>, ...boolean[][]]
>TM1 : readonly [string[], ((number | undefined)[] | undefined)?, ...Arrayify<U>, ...boolean[][]]
type TP1<T extends unknown[]> = Partial<[string, ...T, number]>; // [string?, Partial<T>, number?]
>TP1 : [(string | undefined)?, ...Partial<T>, (number | undefined)?]

View File

@ -0,0 +1,20 @@
// @strict: true
// Repro from #50753
type UnNullify<T> = { [K in keyof T]: NonNullable<T[K]> };
type Foo = UnNullify<[a: 1, b?: 2 | undefined]>;
type Test = [a: 1, b?: 2] extends Foo ? true : false; // true
// Types in the following declarations should be identical
var v: [1, 2?];
var v: [1, (2 | undefined)?];
var v: [a: 1, b?: 2];
var v: [a: 1, b?: 2 | undefined];
var v: UnNullify<[1, 2?]>;
var v: UnNullify<[1, (2 | undefined)?]>;
var v: UnNullify<[a: 1, b?: 2]>;
var v: UnNullify<[a: 1, b?: 2 | undefined]>;