Cherry-pick PR #42943 into release-4.2 (#42964)

Component commits:
361e19bbe8 Ensure no duplicates in named union list

615050437b Add regression test

Co-authored-by: Anders Hejlsberg <andersh@microsoft.com>
This commit is contained in:
TypeScript Bot 2021-02-25 14:18:56 -08:00 committed by GitHub
parent 822cb3a9a3
commit 08ad0e2b88
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 120 additions and 1 deletions

View File

@ -13403,7 +13403,7 @@ namespace ts {
if (t.flags & TypeFlags.Union) {
const origin = (<UnionType>t).origin;
if (t.aliasSymbol || origin && !(origin.flags & TypeFlags.Union)) {
namedUnions.push(t);
pushIfUnique(namedUnions, t);
}
else if (origin && origin.flags & TypeFlags.Union) {
addNamedUnions(namedUnions, (<UnionType>origin).types);

View File

@ -0,0 +1,29 @@
//// [unionOfEnumInference.ts]
// Repro from #42932
enum Enum { A, B, C }
interface Interface<T extends Enum> {
type: T;
}
function foo<T extends Enum>(x: Interface<T>) { }
function bar(x: Interface<Enum.A | Enum.B> | Interface<Enum.C>) {
foo(x);
}
//// [unionOfEnumInference.js]
"use strict";
// Repro from #42932
var Enum;
(function (Enum) {
Enum[Enum["A"] = 0] = "A";
Enum[Enum["B"] = 1] = "B";
Enum[Enum["C"] = 2] = "C";
})(Enum || (Enum = {}));
function foo(x) { }
function bar(x) {
foo(x);
}

View File

@ -0,0 +1,44 @@
=== tests/cases/compiler/unionOfEnumInference.ts ===
// Repro from #42932
enum Enum { A, B, C }
>Enum : Symbol(Enum, Decl(unionOfEnumInference.ts, 0, 0))
>A : Symbol(Enum.A, Decl(unionOfEnumInference.ts, 2, 11))
>B : Symbol(Enum.B, Decl(unionOfEnumInference.ts, 2, 14))
>C : Symbol(Enum.C, Decl(unionOfEnumInference.ts, 2, 17))
interface Interface<T extends Enum> {
>Interface : Symbol(Interface, Decl(unionOfEnumInference.ts, 2, 21))
>T : Symbol(T, Decl(unionOfEnumInference.ts, 4, 20))
>Enum : Symbol(Enum, Decl(unionOfEnumInference.ts, 0, 0))
type: T;
>type : Symbol(Interface.type, Decl(unionOfEnumInference.ts, 4, 37))
>T : Symbol(T, Decl(unionOfEnumInference.ts, 4, 20))
}
function foo<T extends Enum>(x: Interface<T>) { }
>foo : Symbol(foo, Decl(unionOfEnumInference.ts, 6, 1))
>T : Symbol(T, Decl(unionOfEnumInference.ts, 8, 13))
>Enum : Symbol(Enum, Decl(unionOfEnumInference.ts, 0, 0))
>x : Symbol(x, Decl(unionOfEnumInference.ts, 8, 29))
>Interface : Symbol(Interface, Decl(unionOfEnumInference.ts, 2, 21))
>T : Symbol(T, Decl(unionOfEnumInference.ts, 8, 13))
function bar(x: Interface<Enum.A | Enum.B> | Interface<Enum.C>) {
>bar : Symbol(bar, Decl(unionOfEnumInference.ts, 8, 49))
>x : Symbol(x, Decl(unionOfEnumInference.ts, 10, 13))
>Interface : Symbol(Interface, Decl(unionOfEnumInference.ts, 2, 21))
>Enum : Symbol(Enum, Decl(unionOfEnumInference.ts, 0, 0))
>A : Symbol(Enum.A, Decl(unionOfEnumInference.ts, 2, 11))
>Enum : Symbol(Enum, Decl(unionOfEnumInference.ts, 0, 0))
>B : Symbol(Enum.B, Decl(unionOfEnumInference.ts, 2, 14))
>Interface : Symbol(Interface, Decl(unionOfEnumInference.ts, 2, 21))
>Enum : Symbol(Enum, Decl(unionOfEnumInference.ts, 0, 0))
>C : Symbol(Enum.C, Decl(unionOfEnumInference.ts, 2, 17))
foo(x);
>foo : Symbol(foo, Decl(unionOfEnumInference.ts, 6, 1))
>x : Symbol(x, Decl(unionOfEnumInference.ts, 10, 13))
}

View File

@ -0,0 +1,31 @@
=== tests/cases/compiler/unionOfEnumInference.ts ===
// Repro from #42932
enum Enum { A, B, C }
>Enum : Enum
>A : Enum.A
>B : Enum.B
>C : Enum.C
interface Interface<T extends Enum> {
type: T;
>type : T
}
function foo<T extends Enum>(x: Interface<T>) { }
>foo : <T extends Enum>(x: Interface<T>) => void
>x : Interface<T>
function bar(x: Interface<Enum.A | Enum.B> | Interface<Enum.C>) {
>bar : (x: Interface<Enum.A | Enum.B> | Interface<Enum.C>) => void
>x : Interface<Enum.A | Enum.B> | Interface<Enum.C>
>Enum : any
>Enum : any
>Enum : any
foo(x);
>foo(x) : void
>foo : <T extends Enum>(x: Interface<T>) => void
>x : Interface<Enum.A | Enum.B> | Interface<Enum.C>
}

View File

@ -0,0 +1,15 @@
// @strict: true
// Repro from #42932
enum Enum { A, B, C }
interface Interface<T extends Enum> {
type: T;
}
function foo<T extends Enum>(x: Interface<T>) { }
function bar(x: Interface<Enum.A | Enum.B> | Interface<Enum.C>) {
foo(x);
}