diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5fd321dc90a48..86d1021145897 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15866,7 +15866,7 @@ namespace ts { if (unionParent && !result && targetIsOptional) { result = isRelatedTo(source, undefinedType); } - if (unionParent && !result && reportErrors) { + if (unionParent && !result && source.flags & TypeFlags.Union) { // The easiest way to get the right errors here is to un-defer (which may be costly) // If it turns out this is too costly too often, we can replicate the error handling logic within // typeRelatedToSomeType without the discriminatable type branch (as that requires a manifest union diff --git a/tests/baselines/reference/excessPropertyCheckWithUnions.errors.txt b/tests/baselines/reference/excessPropertyCheckWithUnions.errors.txt index efd14c3579779..1776dc16076e2 100644 --- a/tests/baselines/reference/excessPropertyCheckWithUnions.errors.txt +++ b/tests/baselines/reference/excessPropertyCheckWithUnions.errors.txt @@ -26,9 +26,9 @@ tests/cases/compiler/excessPropertyCheckWithUnions.ts(66,9): error TS2322: Type Object literal may only specify known properties, and 'b' does not exist in type 'AN'. tests/cases/compiler/excessPropertyCheckWithUnions.ts(87,5): error TS2322: Type '{ tag: "button"; type: "submit"; href: string; }' is not assignable to type 'Union'. Object literal may only specify known properties, and 'href' does not exist in type 'Button'. -tests/cases/compiler/excessPropertyCheckWithUnions.ts(108,5): error TS2322: Type 'string' is not assignable to type 'IValue'. -tests/cases/compiler/excessPropertyCheckWithUnions.ts(113,67): error TS2322: Type 'string' is not assignable to type 'number'. -tests/cases/compiler/excessPropertyCheckWithUnions.ts(114,63): error TS2322: Type 'string' is not assignable to type 'number'. +tests/cases/compiler/excessPropertyCheckWithUnions.ts(148,5): error TS2322: Type 'string' is not assignable to type 'IValue'. +tests/cases/compiler/excessPropertyCheckWithUnions.ts(153,67): error TS2322: Type 'string' is not assignable to type 'number'. +tests/cases/compiler/excessPropertyCheckWithUnions.ts(154,63): error TS2322: Type 'string' is not assignable to type 'number'. ==== tests/cases/compiler/excessPropertyCheckWithUnions.ts (14 errors) ==== @@ -161,13 +161,53 @@ tests/cases/compiler/excessPropertyCheckWithUnions.ts(114,63): error TS2322: Typ !!! error TS2322: Object literal may only specify known properties, and 'href' does not exist in type 'Button'. }; + + // Repro from #33732 + + interface I1 { + prop1: string; + } + + interface I2 { + prop2: string; + } + + interface I3 extends Record { + + } + + type Properties = + | { [key: string]: never } + | I1 + | I2 + | I3 + ; + + + declare const prop1: string; + declare const prop2: string | undefined; + + function F1(_arg: { props: Properties }) { } + F1({ + props: { + prop1, + prop2, + }, + }); + + function F2(_props: Properties) { } + F2({ + prop1, + prop2, + }); + // Repro from #34611 interface IValue { value: string } - interface StringKeys { + interface StringKeys { [propertyName: string]: IValue; }; diff --git a/tests/baselines/reference/excessPropertyCheckWithUnions.js b/tests/baselines/reference/excessPropertyCheckWithUnions.js index 34cd337705a34..ff17e8641a3aa 100644 --- a/tests/baselines/reference/excessPropertyCheckWithUnions.js +++ b/tests/baselines/reference/excessPropertyCheckWithUnions.js @@ -88,13 +88,53 @@ const obj: Union = { href: 'foo', }; + +// Repro from #33732 + +interface I1 { + prop1: string; +} + +interface I2 { + prop2: string; +} + +interface I3 extends Record { + +} + +type Properties = + | { [key: string]: never } + | I1 + | I2 + | I3 + ; + + +declare const prop1: string; +declare const prop2: string | undefined; + +function F1(_arg: { props: Properties }) { } +F1({ + props: { + prop1, + prop2, + }, +}); + +function F2(_props: Properties) { } +F2({ + prop1, + prop2, +}); + // Repro from #34611 interface IValue { value: string } -interface StringKeys { +interface StringKeys { [propertyName: string]: IValue; }; @@ -170,6 +210,18 @@ var obj = { // should have error here href: 'foo' }; +function F1(_arg) { } +F1({ + props: { + prop1: prop1, + prop2: prop2 + } +}); +function F2(_props) { } +F2({ + prop1: prop1, + prop2: prop2 +}); ; var dataSpecification = { foo: "asdfsadffsd" diff --git a/tests/baselines/reference/excessPropertyCheckWithUnions.symbols b/tests/baselines/reference/excessPropertyCheckWithUnions.symbols index 8fb86125a5731..18db4abf564ac 100644 --- a/tests/baselines/reference/excessPropertyCheckWithUnions.symbols +++ b/tests/baselines/reference/excessPropertyCheckWithUnions.symbols @@ -254,59 +254,143 @@ const obj: Union = { }; + +// Repro from #33732 + +interface I1 { +>I1 : Symbol(I1, Decl(excessPropertyCheckWithUnions.ts, 87, 2)) + + prop1: string; +>prop1 : Symbol(I1.prop1, Decl(excessPropertyCheckWithUnions.ts, 92, 14)) +} + +interface I2 { +>I2 : Symbol(I2, Decl(excessPropertyCheckWithUnions.ts, 94, 1)) + + prop2: string; +>prop2 : Symbol(I2.prop2, Decl(excessPropertyCheckWithUnions.ts, 96, 14)) +} + +interface I3 extends Record { +>I3 : Symbol(I3, Decl(excessPropertyCheckWithUnions.ts, 98, 1)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) + +} + +type Properties = +>Properties : Symbol(Properties, Decl(excessPropertyCheckWithUnions.ts, 102, 1)) + + | { [key: string]: never } +>key : Symbol(key, Decl(excessPropertyCheckWithUnions.ts, 105, 9)) + + | I1 +>I1 : Symbol(I1, Decl(excessPropertyCheckWithUnions.ts, 87, 2)) + + | I2 +>I2 : Symbol(I2, Decl(excessPropertyCheckWithUnions.ts, 94, 1)) + + | I3 +>I3 : Symbol(I3, Decl(excessPropertyCheckWithUnions.ts, 98, 1)) + + ; + + +declare const prop1: string; +>prop1 : Symbol(prop1, Decl(excessPropertyCheckWithUnions.ts, 112, 13)) + +declare const prop2: string | undefined; +>prop2 : Symbol(prop2, Decl(excessPropertyCheckWithUnions.ts, 113, 13)) + +function F1(_arg: { props: Properties }) { } +>F1 : Symbol(F1, Decl(excessPropertyCheckWithUnions.ts, 113, 40)) +>_arg : Symbol(_arg, Decl(excessPropertyCheckWithUnions.ts, 115, 12)) +>props : Symbol(props, Decl(excessPropertyCheckWithUnions.ts, 115, 19)) +>Properties : Symbol(Properties, Decl(excessPropertyCheckWithUnions.ts, 102, 1)) + +F1({ +>F1 : Symbol(F1, Decl(excessPropertyCheckWithUnions.ts, 113, 40)) + + props: { +>props : Symbol(props, Decl(excessPropertyCheckWithUnions.ts, 116, 4)) + + prop1, +>prop1 : Symbol(prop1, Decl(excessPropertyCheckWithUnions.ts, 117, 12)) + + prop2, +>prop2 : Symbol(prop2, Decl(excessPropertyCheckWithUnions.ts, 118, 14)) + + }, +}); + +function F2(_props: Properties) { } +>F2 : Symbol(F2, Decl(excessPropertyCheckWithUnions.ts, 121, 3)) +>_props : Symbol(_props, Decl(excessPropertyCheckWithUnions.ts, 123, 12)) +>Properties : Symbol(Properties, Decl(excessPropertyCheckWithUnions.ts, 102, 1)) + +F2({ +>F2 : Symbol(F2, Decl(excessPropertyCheckWithUnions.ts, 121, 3)) + + prop1, +>prop1 : Symbol(prop1, Decl(excessPropertyCheckWithUnions.ts, 124, 4)) + + prop2, +>prop2 : Symbol(prop2, Decl(excessPropertyCheckWithUnions.ts, 125, 10)) + +}); + // Repro from #34611 interface IValue { ->IValue : Symbol(IValue, Decl(excessPropertyCheckWithUnions.ts, 87, 2)) +>IValue : Symbol(IValue, Decl(excessPropertyCheckWithUnions.ts, 127, 3)) value: string ->value : Symbol(IValue.value, Decl(excessPropertyCheckWithUnions.ts, 91, 18)) +>value : Symbol(IValue.value, Decl(excessPropertyCheckWithUnions.ts, 131, 18)) } -interface StringKeys { ->StringKeys : Symbol(StringKeys, Decl(excessPropertyCheckWithUnions.ts, 93, 1)) +interface StringKeys { +>StringKeys : Symbol(StringKeys, Decl(excessPropertyCheckWithUnions.ts, 133, 1)) [propertyName: string]: IValue; ->propertyName : Symbol(propertyName, Decl(excessPropertyCheckWithUnions.ts, 96, 5)) ->IValue : Symbol(IValue, Decl(excessPropertyCheckWithUnions.ts, 87, 2)) +>propertyName : Symbol(propertyName, Decl(excessPropertyCheckWithUnions.ts, 136, 5)) +>IValue : Symbol(IValue, Decl(excessPropertyCheckWithUnions.ts, 127, 3)) }; interface NumberKeys { ->NumberKeys : Symbol(NumberKeys, Decl(excessPropertyCheckWithUnions.ts, 97, 2)) +>NumberKeys : Symbol(NumberKeys, Decl(excessPropertyCheckWithUnions.ts, 137, 2)) [propertyName: number]: IValue; ->propertyName : Symbol(propertyName, Decl(excessPropertyCheckWithUnions.ts, 100, 5)) ->IValue : Symbol(IValue, Decl(excessPropertyCheckWithUnions.ts, 87, 2)) +>propertyName : Symbol(propertyName, Decl(excessPropertyCheckWithUnions.ts, 140, 5)) +>IValue : Symbol(IValue, Decl(excessPropertyCheckWithUnions.ts, 127, 3)) } type ObjectDataSpecification = StringKeys | NumberKeys; ->ObjectDataSpecification : Symbol(ObjectDataSpecification, Decl(excessPropertyCheckWithUnions.ts, 101, 1)) ->StringKeys : Symbol(StringKeys, Decl(excessPropertyCheckWithUnions.ts, 93, 1)) ->NumberKeys : Symbol(NumberKeys, Decl(excessPropertyCheckWithUnions.ts, 97, 2)) +>ObjectDataSpecification : Symbol(ObjectDataSpecification, Decl(excessPropertyCheckWithUnions.ts, 141, 1)) +>StringKeys : Symbol(StringKeys, Decl(excessPropertyCheckWithUnions.ts, 133, 1)) +>NumberKeys : Symbol(NumberKeys, Decl(excessPropertyCheckWithUnions.ts, 137, 2)) const dataSpecification: ObjectDataSpecification = { // Error ->dataSpecification : Symbol(dataSpecification, Decl(excessPropertyCheckWithUnions.ts, 106, 5)) ->ObjectDataSpecification : Symbol(ObjectDataSpecification, Decl(excessPropertyCheckWithUnions.ts, 101, 1)) +>dataSpecification : Symbol(dataSpecification, Decl(excessPropertyCheckWithUnions.ts, 146, 5)) +>ObjectDataSpecification : Symbol(ObjectDataSpecification, Decl(excessPropertyCheckWithUnions.ts, 141, 1)) foo: "asdfsadffsd" ->foo : Symbol(foo, Decl(excessPropertyCheckWithUnions.ts, 106, 52)) +>foo : Symbol(foo, Decl(excessPropertyCheckWithUnions.ts, 146, 52)) }; // Repro from #34611 const obj1: { [x: string]: number } | { [x: number]: number } = { a: 'abc' }; // Error ->obj1 : Symbol(obj1, Decl(excessPropertyCheckWithUnions.ts, 112, 5)) ->x : Symbol(x, Decl(excessPropertyCheckWithUnions.ts, 112, 15)) ->x : Symbol(x, Decl(excessPropertyCheckWithUnions.ts, 112, 41)) ->a : Symbol(a, Decl(excessPropertyCheckWithUnions.ts, 112, 65)) +>obj1 : Symbol(obj1, Decl(excessPropertyCheckWithUnions.ts, 152, 5)) +>x : Symbol(x, Decl(excessPropertyCheckWithUnions.ts, 152, 15)) +>x : Symbol(x, Decl(excessPropertyCheckWithUnions.ts, 152, 41)) +>a : Symbol(a, Decl(excessPropertyCheckWithUnions.ts, 152, 65)) const obj2: { [x: string]: number } | { a: number } = { a: 5, c: 'abc' }; // Error ->obj2 : Symbol(obj2, Decl(excessPropertyCheckWithUnions.ts, 113, 5)) ->x : Symbol(x, Decl(excessPropertyCheckWithUnions.ts, 113, 15)) ->a : Symbol(a, Decl(excessPropertyCheckWithUnions.ts, 113, 39)) ->a : Symbol(a, Decl(excessPropertyCheckWithUnions.ts, 113, 55)) ->c : Symbol(c, Decl(excessPropertyCheckWithUnions.ts, 113, 61)) +>obj2 : Symbol(obj2, Decl(excessPropertyCheckWithUnions.ts, 153, 5)) +>x : Symbol(x, Decl(excessPropertyCheckWithUnions.ts, 153, 15)) +>a : Symbol(a, Decl(excessPropertyCheckWithUnions.ts, 153, 39)) +>a : Symbol(a, Decl(excessPropertyCheckWithUnions.ts, 153, 55)) +>c : Symbol(c, Decl(excessPropertyCheckWithUnions.ts, 153, 61)) diff --git a/tests/baselines/reference/excessPropertyCheckWithUnions.types b/tests/baselines/reference/excessPropertyCheckWithUnions.types index 38e9a6c81e7a4..5f19bbd3ffbfc 100644 --- a/tests/baselines/reference/excessPropertyCheckWithUnions.types +++ b/tests/baselines/reference/excessPropertyCheckWithUnions.types @@ -312,6 +312,81 @@ const obj: Union = { }; + +// Repro from #33732 + +interface I1 { + prop1: string; +>prop1 : string +} + +interface I2 { + prop2: string; +>prop2 : string +} + +interface I3 extends Record { + +} + +type Properties = +>Properties : Properties + + | { [key: string]: never } +>key : string + + | I1 + | I2 + | I3 + ; + + +declare const prop1: string; +>prop1 : string + +declare const prop2: string | undefined; +>prop2 : string | undefined + +function F1(_arg: { props: Properties }) { } +>F1 : (_arg: { props: Properties; }) => void +>_arg : { props: Properties; } +>props : Properties + +F1({ +>F1({ props: { prop1, prop2, },}) : void +>F1 : (_arg: { props: Properties; }) => void +>{ props: { prop1, prop2, },} : { props: { prop1: string; prop2: string | undefined; }; } + + props: { +>props : { prop1: string; prop2: string | undefined; } +>{ prop1, prop2, } : { prop1: string; prop2: string | undefined; } + + prop1, +>prop1 : string + + prop2, +>prop2 : string | undefined + + }, +}); + +function F2(_props: Properties) { } +>F2 : (_props: Properties) => void +>_props : Properties + +F2({ +>F2({ prop1, prop2,}) : void +>F2 : (_props: Properties) => void +>{ prop1, prop2,} : { prop1: string; prop2: string | undefined; } + + prop1, +>prop1 : string + + prop2, +>prop2 : string | undefined + +}); + // Repro from #34611 interface IValue { @@ -319,7 +394,7 @@ interface IValue { >value : string } -interface StringKeys { +interface StringKeys { [propertyName: string]: IValue; >propertyName : string diff --git a/tests/cases/compiler/excessPropertyCheckWithUnions.ts b/tests/cases/compiler/excessPropertyCheckWithUnions.ts index 635c5c2a7d3f6..9e6a65961f628 100644 --- a/tests/cases/compiler/excessPropertyCheckWithUnions.ts +++ b/tests/cases/compiler/excessPropertyCheckWithUnions.ts @@ -88,13 +88,53 @@ const obj: Union = { href: 'foo', }; + +// Repro from #33732 + +interface I1 { + prop1: string; +} + +interface I2 { + prop2: string; +} + +interface I3 extends Record { + +} + +type Properties = + | { [key: string]: never } + | I1 + | I2 + | I3 + ; + + +declare const prop1: string; +declare const prop2: string | undefined; + +function F1(_arg: { props: Properties }) { } +F1({ + props: { + prop1, + prop2, + }, +}); + +function F2(_props: Properties) { } +F2({ + prop1, + prop2, +}); + // Repro from #34611 interface IValue { value: string } -interface StringKeys { +interface StringKeys { [propertyName: string]: IValue; };