diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 44d6ca66853a6..23b1e2912f472 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15901,7 +15901,7 @@ namespace ts { // with respect to T. We do not report errors here, as we will use the existing // error result from checking each constituent of the union. if (source.flags & (TypeFlags.Object | TypeFlags.Intersection) && target.flags & TypeFlags.Union) { - const objectOnlyTarget = extractTypesOfKind(target, TypeFlags.Object); + const objectOnlyTarget = extractTypesOfKind(target, TypeFlags.Object | TypeFlags.Intersection | TypeFlags.Substitution); if (objectOnlyTarget.flags & TypeFlags.Union) { const result = typeRelatedToDiscriminatedType(source, objectOnlyTarget as UnionType); if (result) { @@ -15998,7 +15998,7 @@ namespace ts { // NOTE: See ~/tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithDiscriminatedUnion.ts // for examples. - const sourceProperties = getPropertiesOfObjectType(source); + const sourceProperties = getPropertiesOfType(source); const sourcePropertiesFiltered = findDiscriminantProperties(sourceProperties, target); if (!sourcePropertiesFiltered) return Ternary.False; @@ -16037,7 +16037,7 @@ namespace ts { outer: for (const type of target.types) { for (let i = 0; i < sourcePropertiesFiltered.length; i++) { const sourceProperty = sourcePropertiesFiltered[i]; - const targetProperty = getPropertyOfObjectType(type, sourceProperty.escapedName); + const targetProperty = getPropertyOfType(type, sourceProperty.escapedName); if (!targetProperty) continue outer; if (sourceProperty === targetProperty) continue; // We compare the source property to the target in the context of a single discriminant type. diff --git a/tests/baselines/reference/discriminableUnionWithIntersectedMembers.js b/tests/baselines/reference/discriminableUnionWithIntersectedMembers.js new file mode 100644 index 0000000000000..3be6283454be0 --- /dev/null +++ b/tests/baselines/reference/discriminableUnionWithIntersectedMembers.js @@ -0,0 +1,21 @@ +//// [discriminableUnionWithIntersectedMembers.ts] +// regression test for https://github.com/microsoft/TypeScript/issues/33243 +type X = + | { x: 'x', y: number } & { y: number } + | { x: 'y', y: number, z?: boolean } & { y: number } + +// error +const x: X = 4 as any as { x: 'x' | 'y', y: number }; + +type Y = + | { x: 'x', y: number } + | { x: 'y', y: number, z?: boolean } + +// no error +const y: Y = 4 as any as { x: 'x' | 'y', y: number }; + +//// [discriminableUnionWithIntersectedMembers.js] +// error +var x = 4; +// no error +var y = 4; diff --git a/tests/baselines/reference/discriminableUnionWithIntersectedMembers.symbols b/tests/baselines/reference/discriminableUnionWithIntersectedMembers.symbols new file mode 100644 index 0000000000000..49725db5bfb0d --- /dev/null +++ b/tests/baselines/reference/discriminableUnionWithIntersectedMembers.symbols @@ -0,0 +1,42 @@ +=== tests/cases/compiler/discriminableUnionWithIntersectedMembers.ts === +// regression test for https://github.com/microsoft/TypeScript/issues/33243 +type X = +>X : Symbol(X, Decl(discriminableUnionWithIntersectedMembers.ts, 0, 0)) + + | { x: 'x', y: number } & { y: number } +>x : Symbol(x, Decl(discriminableUnionWithIntersectedMembers.ts, 2, 4)) +>y : Symbol(y, Decl(discriminableUnionWithIntersectedMembers.ts, 2, 12)) +>y : Symbol(y, Decl(discriminableUnionWithIntersectedMembers.ts, 2, 28)) + + | { x: 'y', y: number, z?: boolean } & { y: number } +>x : Symbol(x, Decl(discriminableUnionWithIntersectedMembers.ts, 3, 4)) +>y : Symbol(y, Decl(discriminableUnionWithIntersectedMembers.ts, 3, 12)) +>z : Symbol(z, Decl(discriminableUnionWithIntersectedMembers.ts, 3, 23)) +>y : Symbol(y, Decl(discriminableUnionWithIntersectedMembers.ts, 3, 41)) + +// error +const x: X = 4 as any as { x: 'x' | 'y', y: number }; +>x : Symbol(x, Decl(discriminableUnionWithIntersectedMembers.ts, 6, 5)) +>X : Symbol(X, Decl(discriminableUnionWithIntersectedMembers.ts, 0, 0)) +>x : Symbol(x, Decl(discriminableUnionWithIntersectedMembers.ts, 6, 26)) +>y : Symbol(y, Decl(discriminableUnionWithIntersectedMembers.ts, 6, 40)) + +type Y = +>Y : Symbol(Y, Decl(discriminableUnionWithIntersectedMembers.ts, 6, 53)) + + | { x: 'x', y: number } +>x : Symbol(x, Decl(discriminableUnionWithIntersectedMembers.ts, 9, 4)) +>y : Symbol(y, Decl(discriminableUnionWithIntersectedMembers.ts, 9, 12)) + + | { x: 'y', y: number, z?: boolean } +>x : Symbol(x, Decl(discriminableUnionWithIntersectedMembers.ts, 10, 4)) +>y : Symbol(y, Decl(discriminableUnionWithIntersectedMembers.ts, 10, 12)) +>z : Symbol(z, Decl(discriminableUnionWithIntersectedMembers.ts, 10, 23)) + +// no error +const y: Y = 4 as any as { x: 'x' | 'y', y: number }; +>y : Symbol(y, Decl(discriminableUnionWithIntersectedMembers.ts, 13, 5)) +>Y : Symbol(Y, Decl(discriminableUnionWithIntersectedMembers.ts, 6, 53)) +>x : Symbol(x, Decl(discriminableUnionWithIntersectedMembers.ts, 13, 26)) +>y : Symbol(y, Decl(discriminableUnionWithIntersectedMembers.ts, 13, 40)) + diff --git a/tests/baselines/reference/discriminableUnionWithIntersectedMembers.types b/tests/baselines/reference/discriminableUnionWithIntersectedMembers.types new file mode 100644 index 0000000000000..8f7899806f6d7 --- /dev/null +++ b/tests/baselines/reference/discriminableUnionWithIntersectedMembers.types @@ -0,0 +1,46 @@ +=== tests/cases/compiler/discriminableUnionWithIntersectedMembers.ts === +// regression test for https://github.com/microsoft/TypeScript/issues/33243 +type X = +>X : X + + | { x: 'x', y: number } & { y: number } +>x : "x" +>y : number +>y : number + + | { x: 'y', y: number, z?: boolean } & { y: number } +>x : "y" +>y : number +>z : boolean +>y : number + +// error +const x: X = 4 as any as { x: 'x' | 'y', y: number }; +>x : X +>4 as any as { x: 'x' | 'y', y: number } : { x: "x" | "y"; y: number; } +>4 as any : any +>4 : 4 +>x : "x" | "y" +>y : number + +type Y = +>Y : Y + + | { x: 'x', y: number } +>x : "x" +>y : number + + | { x: 'y', y: number, z?: boolean } +>x : "y" +>y : number +>z : boolean + +// no error +const y: Y = 4 as any as { x: 'x' | 'y', y: number }; +>y : Y +>4 as any as { x: 'x' | 'y', y: number } : { x: "x" | "y"; y: number; } +>4 as any : any +>4 : 4 +>x : "x" | "y" +>y : number + diff --git a/tests/cases/compiler/discriminableUnionWithIntersectedMembers.ts b/tests/cases/compiler/discriminableUnionWithIntersectedMembers.ts new file mode 100644 index 0000000000000..445431101b372 --- /dev/null +++ b/tests/cases/compiler/discriminableUnionWithIntersectedMembers.ts @@ -0,0 +1,14 @@ +// regression test for https://github.com/microsoft/TypeScript/issues/33243 +type X = + | { x: 'x', y: number } & { y: number } + | { x: 'y', y: number, z?: boolean } & { y: number } + +// error +const x: X = 4 as any as { x: 'x' | 'y', y: number }; + +type Y = + | { x: 'x', y: number } + | { x: 'y', y: number, z?: boolean } + +// no error +const y: Y = 4 as any as { x: 'x' | 'y', y: number }; \ No newline at end of file