Fix type parameter leak (#35949)

* Fix cloneSignature to include unionSignatures property

* Add regression test
This commit is contained in:
Anders Hejlsberg 2020-01-03 07:54:38 -10:00 committed by GitHub
parent 024b8c1e5f
commit a8944e6844
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 164 additions and 0 deletions

View File

@ -8774,6 +8774,7 @@ namespace ts {
sig.minArgumentCount = minArgumentCount;
sig.target = undefined;
sig.mapper = undefined;
sig.unionSignatures = undefined;
return sig;
}
@ -8782,6 +8783,7 @@ namespace ts {
/*resolvedTypePredicate*/ undefined, sig.minArgumentCount, sig.flags & SignatureFlags.PropagatingFlags);
result.target = sig.target;
result.mapper = sig.mapper;
result.unionSignatures = sig.unionSignatures;
return result;
}

View File

@ -0,0 +1,29 @@
//// [typeParameterLeak.ts]
// Repro from #35655
interface Box<T> { data: T }
type BoxTypes = Box<{ x: string }> | Box<{ y: string }>;
type BoxFactoryFactory<TBox> = TBox extends Box<infer T> ? {
(arg: T): BoxFactory<TBox> | undefined
} : never;
interface BoxFactory<A> {
getBox(): A,
}
declare const f: BoxFactoryFactory<BoxTypes>;
const b = f({ x: "", y: "" })?.getBox();
if (b) {
const x = b.data;
}
//// [typeParameterLeak.js]
"use strict";
// Repro from #35655
var _a;
var b = (_a = f({ x: "", y: "" })) === null || _a === void 0 ? void 0 : _a.getBox();
if (b) {
var x = b.data;
}

View File

@ -0,0 +1,63 @@
=== tests/cases/compiler/typeParameterLeak.ts ===
// Repro from #35655
interface Box<T> { data: T }
>Box : Symbol(Box, Decl(typeParameterLeak.ts, 0, 0))
>T : Symbol(T, Decl(typeParameterLeak.ts, 2, 14))
>data : Symbol(Box.data, Decl(typeParameterLeak.ts, 2, 18))
>T : Symbol(T, Decl(typeParameterLeak.ts, 2, 14))
type BoxTypes = Box<{ x: string }> | Box<{ y: string }>;
>BoxTypes : Symbol(BoxTypes, Decl(typeParameterLeak.ts, 2, 28))
>Box : Symbol(Box, Decl(typeParameterLeak.ts, 0, 0))
>x : Symbol(x, Decl(typeParameterLeak.ts, 3, 21))
>Box : Symbol(Box, Decl(typeParameterLeak.ts, 0, 0))
>y : Symbol(y, Decl(typeParameterLeak.ts, 3, 42))
type BoxFactoryFactory<TBox> = TBox extends Box<infer T> ? {
>BoxFactoryFactory : Symbol(BoxFactoryFactory, Decl(typeParameterLeak.ts, 3, 56))
>TBox : Symbol(TBox, Decl(typeParameterLeak.ts, 5, 23))
>TBox : Symbol(TBox, Decl(typeParameterLeak.ts, 5, 23))
>Box : Symbol(Box, Decl(typeParameterLeak.ts, 0, 0))
>T : Symbol(T, Decl(typeParameterLeak.ts, 5, 53))
(arg: T): BoxFactory<TBox> | undefined
>arg : Symbol(arg, Decl(typeParameterLeak.ts, 6, 3))
>T : Symbol(T, Decl(typeParameterLeak.ts, 5, 53))
>BoxFactory : Symbol(BoxFactory, Decl(typeParameterLeak.ts, 7, 10))
>TBox : Symbol(TBox, Decl(typeParameterLeak.ts, 5, 23))
} : never;
interface BoxFactory<A> {
>BoxFactory : Symbol(BoxFactory, Decl(typeParameterLeak.ts, 7, 10))
>A : Symbol(A, Decl(typeParameterLeak.ts, 9, 21))
getBox(): A,
>getBox : Symbol(BoxFactory.getBox, Decl(typeParameterLeak.ts, 9, 25))
>A : Symbol(A, Decl(typeParameterLeak.ts, 9, 21))
}
declare const f: BoxFactoryFactory<BoxTypes>;
>f : Symbol(f, Decl(typeParameterLeak.ts, 13, 13))
>BoxFactoryFactory : Symbol(BoxFactoryFactory, Decl(typeParameterLeak.ts, 3, 56))
>BoxTypes : Symbol(BoxTypes, Decl(typeParameterLeak.ts, 2, 28))
const b = f({ x: "", y: "" })?.getBox();
>b : Symbol(b, Decl(typeParameterLeak.ts, 14, 5))
>f({ x: "", y: "" })?.getBox : Symbol(BoxFactory.getBox, Decl(typeParameterLeak.ts, 9, 25), Decl(typeParameterLeak.ts, 9, 25))
>f : Symbol(f, Decl(typeParameterLeak.ts, 13, 13))
>x : Symbol(x, Decl(typeParameterLeak.ts, 14, 13))
>y : Symbol(y, Decl(typeParameterLeak.ts, 14, 20))
>getBox : Symbol(BoxFactory.getBox, Decl(typeParameterLeak.ts, 9, 25), Decl(typeParameterLeak.ts, 9, 25))
if (b) {
>b : Symbol(b, Decl(typeParameterLeak.ts, 14, 5))
const x = b.data;
>x : Symbol(x, Decl(typeParameterLeak.ts, 16, 7))
>b.data : Symbol(Box.data, Decl(typeParameterLeak.ts, 2, 18), Decl(typeParameterLeak.ts, 2, 18))
>b : Symbol(b, Decl(typeParameterLeak.ts, 14, 5))
>data : Symbol(Box.data, Decl(typeParameterLeak.ts, 2, 18), Decl(typeParameterLeak.ts, 2, 18))
}

View File

@ -0,0 +1,50 @@
=== tests/cases/compiler/typeParameterLeak.ts ===
// Repro from #35655
interface Box<T> { data: T }
>data : T
type BoxTypes = Box<{ x: string }> | Box<{ y: string }>;
>BoxTypes : BoxTypes
>x : string
>y : string
type BoxFactoryFactory<TBox> = TBox extends Box<infer T> ? {
>BoxFactoryFactory : BoxFactoryFactory<TBox>
(arg: T): BoxFactory<TBox> | undefined
>arg : T
} : never;
interface BoxFactory<A> {
getBox(): A,
>getBox : () => A
}
declare const f: BoxFactoryFactory<BoxTypes>;
>f : ((arg: { x: string; }) => BoxFactory<Box<{ x: string; }>> | undefined) | ((arg: { y: string; }) => BoxFactory<Box<{ y: string; }>> | undefined)
const b = f({ x: "", y: "" })?.getBox();
>b : Box<{ x: string; }> | Box<{ y: string; }> | undefined
>f({ x: "", y: "" })?.getBox() : Box<{ x: string; }> | Box<{ y: string; }> | undefined
>f({ x: "", y: "" })?.getBox : (() => Box<{ x: string; }>) | (() => Box<{ y: string; }>) | undefined
>f({ x: "", y: "" }) : BoxFactory<Box<{ x: string; }>> | BoxFactory<Box<{ y: string; }>> | undefined
>f : ((arg: { x: string; }) => BoxFactory<Box<{ x: string; }>> | undefined) | ((arg: { y: string; }) => BoxFactory<Box<{ y: string; }>> | undefined)
>{ x: "", y: "" } : { x: string; y: string; }
>x : string
>"" : ""
>y : string
>"" : ""
>getBox : (() => Box<{ x: string; }>) | (() => Box<{ y: string; }>) | undefined
if (b) {
>b : Box<{ x: string; }> | Box<{ y: string; }> | undefined
const x = b.data;
>x : { x: string; } | { y: string; }
>b.data : { x: string; } | { y: string; }
>b : BoxTypes
>data : { x: string; } | { y: string; }
}

View File

@ -0,0 +1,20 @@
// @strict: true
// Repro from #35655
interface Box<T> { data: T }
type BoxTypes = Box<{ x: string }> | Box<{ y: string }>;
type BoxFactoryFactory<TBox> = TBox extends Box<infer T> ? {
(arg: T): BoxFactory<TBox> | undefined
} : never;
interface BoxFactory<A> {
getBox(): A,
}
declare const f: BoxFactoryFactory<BoxTypes>;
const b = f({ x: "", y: "" })?.getBox();
if (b) {
const x = b.data;
}