Merge pull request #28948 from Microsoft/discriminatedUnionIndexSignature

Fix crash related to discriminated unions with index signatures
This commit is contained in:
Anders Hejlsberg
2018-12-10 17:16:30 -08:00
committed by GitHub
6 changed files with 185 additions and 1 deletions

View File

@@ -4715,6 +4715,10 @@ namespace ts {
return prop ? getTypeOfSymbol(prop) : undefined;
}
function getTypeOfPropertyOrIndexSignature(type: Type, name: __String): Type {
return getTypeOfPropertyOfType(type, name) || isNumericLiteralName(name) && getIndexTypeOfType(type, IndexKind.Number) || getIndexTypeOfType(type, IndexKind.String) || unknownType;
}
function isTypeAny(type: Type | undefined) {
return type && (type.flags & TypeFlags.Any) !== 0;
}
@@ -15657,7 +15661,7 @@ namespace ts {
}
const propType = getTypeOfPropertyOfType(type, propName);
const narrowedPropType = propType && narrowType(propType);
return propType === narrowedPropType ? type : filterType(type, t => isTypeComparableTo(getTypeOfPropertyOfType(t, propName)!, narrowedPropType!));
return propType === narrowedPropType ? type : filterType(type, t => isTypeComparableTo(getTypeOfPropertyOrIndexSignature(t, propName), narrowedPropType!));
}
function narrowTypeByTruthiness(type: Type, expr: Expression, assumeTrue: boolean): Type {

View File

@@ -83,4 +83,26 @@ tests/cases/conformance/types/union/discriminatedUnionTypes2.ts(32,11): error TS
const data: null = carrier.data
}
}
// Repro from #28935
type Foo = { tag: true, x: number } | { tag: false, y: number } | { [x: string]: string };
function f30(foo: Foo) {
if (foo.tag) {
foo;
}
else {
foo;
}
}
function f31(foo: Foo) {
if (foo.tag === true) {
foo;
}
else {
foo;
}
}

View File

@@ -71,6 +71,28 @@ function f20<Data>(carrier: DataCarrier<Data>) {
const data: null = carrier.data
}
}
// Repro from #28935
type Foo = { tag: true, x: number } | { tag: false, y: number } | { [x: string]: string };
function f30(foo: Foo) {
if (foo.tag) {
foo;
}
else {
foo;
}
}
function f31(foo: Foo) {
if (foo.tag === true) {
foo;
}
else {
foo;
}
}
//// [discriminatedUnionTypes2.js]
@@ -126,3 +148,19 @@ function f20(carrier) {
var data = carrier.data;
}
}
function f30(foo) {
if (foo.tag) {
foo;
}
else {
foo;
}
}
function f31(foo) {
if (foo.tag === true) {
foo;
}
else {
foo;
}
}

View File

@@ -225,3 +225,51 @@ function f20<Data>(carrier: DataCarrier<Data>) {
}
}
// Repro from #28935
type Foo = { tag: true, x: number } | { tag: false, y: number } | { [x: string]: string };
>Foo : Symbol(Foo, Decl(discriminatedUnionTypes2.ts, 71, 1))
>tag : Symbol(tag, Decl(discriminatedUnionTypes2.ts, 75, 12))
>x : Symbol(x, Decl(discriminatedUnionTypes2.ts, 75, 23))
>tag : Symbol(tag, Decl(discriminatedUnionTypes2.ts, 75, 39))
>y : Symbol(y, Decl(discriminatedUnionTypes2.ts, 75, 51))
>x : Symbol(x, Decl(discriminatedUnionTypes2.ts, 75, 69))
function f30(foo: Foo) {
>f30 : Symbol(f30, Decl(discriminatedUnionTypes2.ts, 75, 90))
>foo : Symbol(foo, Decl(discriminatedUnionTypes2.ts, 77, 13))
>Foo : Symbol(Foo, Decl(discriminatedUnionTypes2.ts, 71, 1))
if (foo.tag) {
>foo.tag : Symbol(tag, Decl(discriminatedUnionTypes2.ts, 75, 12), Decl(discriminatedUnionTypes2.ts, 75, 39))
>foo : Symbol(foo, Decl(discriminatedUnionTypes2.ts, 77, 13))
>tag : Symbol(tag, Decl(discriminatedUnionTypes2.ts, 75, 12), Decl(discriminatedUnionTypes2.ts, 75, 39))
foo;
>foo : Symbol(foo, Decl(discriminatedUnionTypes2.ts, 77, 13))
}
else {
foo;
>foo : Symbol(foo, Decl(discriminatedUnionTypes2.ts, 77, 13))
}
}
function f31(foo: Foo) {
>f31 : Symbol(f31, Decl(discriminatedUnionTypes2.ts, 84, 1))
>foo : Symbol(foo, Decl(discriminatedUnionTypes2.ts, 86, 13))
>Foo : Symbol(Foo, Decl(discriminatedUnionTypes2.ts, 71, 1))
if (foo.tag === true) {
>foo.tag : Symbol(tag, Decl(discriminatedUnionTypes2.ts, 75, 12), Decl(discriminatedUnionTypes2.ts, 75, 39))
>foo : Symbol(foo, Decl(discriminatedUnionTypes2.ts, 86, 13))
>tag : Symbol(tag, Decl(discriminatedUnionTypes2.ts, 75, 12), Decl(discriminatedUnionTypes2.ts, 75, 39))
foo;
>foo : Symbol(foo, Decl(discriminatedUnionTypes2.ts, 86, 13))
}
else {
foo;
>foo : Symbol(foo, Decl(discriminatedUnionTypes2.ts, 86, 13))
}
}

View File

@@ -239,3 +239,53 @@ function f20<Data>(carrier: DataCarrier<Data>) {
}
}
// Repro from #28935
type Foo = { tag: true, x: number } | { tag: false, y: number } | { [x: string]: string };
>Foo : Foo
>tag : true
>true : true
>x : number
>tag : false
>false : false
>y : number
>x : string
function f30(foo: Foo) {
>f30 : (foo: Foo) => void
>foo : Foo
if (foo.tag) {
>foo.tag : string | boolean
>foo : Foo
>tag : string | boolean
foo;
>foo : { tag: true; x: number; } | { [x: string]: string; }
}
else {
foo;
>foo : { tag: false; y: number; } | { [x: string]: string; }
}
}
function f31(foo: Foo) {
>f31 : (foo: Foo) => void
>foo : Foo
if (foo.tag === true) {
>foo.tag === true : boolean
>foo.tag : string | boolean
>foo : Foo
>tag : string | boolean
>true : true
foo;
>foo : { tag: true; x: number; }
}
else {
foo;
>foo : { tag: false; y: number; } | { [x: string]: string; }
}
}

View File

@@ -72,3 +72,25 @@ function f20<Data>(carrier: DataCarrier<Data>) {
const data: null = carrier.data
}
}
// Repro from #28935
type Foo = { tag: true, x: number } | { tag: false, y: number } | { [x: string]: string };
function f30(foo: Foo) {
if (foo.tag) {
foo;
}
else {
foo;
}
}
function f31(foo: Foo) {
if (foo.tag === true) {
foo;
}
else {
foo;
}
}