diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4ddec362457b4..d96adbcdb582b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -23235,7 +23235,8 @@ namespace ts { function checkSpreadPropOverrides(type: Type, props: SymbolTable, spread: SpreadAssignment | JsxSpreadAttribute) { for (const right of getPropertiesOfType(type)) { const left = props.get(right.escapedName); - if (left && !maybeTypeOfKind(getTypeOfSymbol(right), TypeFlags.Nullable)) { + const rightType = getTypeOfSymbol(right); + if (left && !maybeTypeOfKind(rightType, TypeFlags.Nullable) && !(maybeTypeOfKind(rightType, TypeFlags.Any) && right.flags & SymbolFlags.Optional)) { const diagnostic = error(left.valueDeclaration, Diagnostics._0_is_specified_more_than_once_so_this_usage_will_be_overwritten, unescapeLeadingUnderscores(left.escapedName)); addRelatedInfo(diagnostic, createDiagnosticForNode(spread, Diagnostics.This_spread_always_overwrites_this_property)); } diff --git a/tests/baselines/reference/spreadOverwritesPropertyStrict.errors.txt b/tests/baselines/reference/spreadOverwritesPropertyStrict.errors.txt index b671a9ca73d08..354e7d667a5ee 100644 --- a/tests/baselines/reference/spreadOverwritesPropertyStrict.errors.txt +++ b/tests/baselines/reference/spreadOverwritesPropertyStrict.errors.txt @@ -1,9 +1,10 @@ tests/cases/conformance/types/spread/spreadOverwritesPropertyStrict.ts(3,17): error TS2783: 'b' is specified more than once, so this usage will be overwritten. tests/cases/conformance/types/spread/spreadOverwritesPropertyStrict.ts(15,14): error TS2783: 'x' is specified more than once, so this usage will be overwritten. tests/cases/conformance/types/spread/spreadOverwritesPropertyStrict.ts(24,14): error TS2783: 'command' is specified more than once, so this usage will be overwritten. +tests/cases/conformance/types/spread/spreadOverwritesPropertyStrict.ts(28,14): error TS2783: 'a' is specified more than once, so this usage will be overwritten. -==== tests/cases/conformance/types/spread/spreadOverwritesPropertyStrict.ts (3 errors) ==== +==== tests/cases/conformance/types/spread/spreadOverwritesPropertyStrict.ts (4 errors) ==== declare var ab: { a: number, b: number }; declare var abq: { a: number, b?: number }; var unused1 = { b: 1, ...ab } // error @@ -38,4 +39,15 @@ tests/cases/conformance/types/spread/spreadOverwritesPropertyStrict.ts(24,14): e !!! error TS2783: 'command' is specified more than once, so this usage will be overwritten. !!! related TS2785 tests/cases/conformance/types/spread/spreadOverwritesPropertyStrict.ts:24:67: This spread always overwrites this property. } + + function l(anyrequired: { a: any }) { + return { a: 'zzz', ...anyrequired } // error + ~~~~~~~~ +!!! error TS2783: 'a' is specified more than once, so this usage will be overwritten. +!!! related TS2785 tests/cases/conformance/types/spread/spreadOverwritesPropertyStrict.ts:28:24: This spread always overwrites this property. + } + function m(anyoptional: { a?: any }) { + return { a: 'zzz', ...anyoptional } // ok + } + \ No newline at end of file diff --git a/tests/baselines/reference/spreadOverwritesPropertyStrict.js b/tests/baselines/reference/spreadOverwritesPropertyStrict.js index 6ca70a1963fa0..692a48536d5b7 100644 --- a/tests/baselines/reference/spreadOverwritesPropertyStrict.js +++ b/tests/baselines/reference/spreadOverwritesPropertyStrict.js @@ -24,6 +24,14 @@ function j() { function k(t: { command: string, ok: string }) { return { command: "hi", ...{ spoiler: true }, spoiler2: true, ...t } // error } + +function l(anyrequired: { a: any }) { + return { a: 'zzz', ...anyrequired } // error +} +function m(anyoptional: { a?: any }) { + return { a: 'zzz', ...anyoptional } // ok +} + //// [spreadOverwritesPropertyStrict.js] @@ -62,3 +70,9 @@ function j() { function k(t) { return __assign(__assign(__assign({ command: "hi" }, { spoiler: true }), { spoiler2: true }), t); // error } +function l(anyrequired) { + return __assign({ a: 'zzz' }, anyrequired); // error +} +function m(anyoptional) { + return __assign({ a: 'zzz' }, anyoptional); // ok +} diff --git a/tests/baselines/reference/spreadOverwritesPropertyStrict.symbols b/tests/baselines/reference/spreadOverwritesPropertyStrict.symbols index f9ff36c6598bd..0a5359c7f228b 100644 --- a/tests/baselines/reference/spreadOverwritesPropertyStrict.symbols +++ b/tests/baselines/reference/spreadOverwritesPropertyStrict.symbols @@ -94,3 +94,23 @@ function k(t: { command: string, ok: string }) { >t : Symbol(t, Decl(spreadOverwritesPropertyStrict.ts, 22, 11)) } +function l(anyrequired: { a: any }) { +>l : Symbol(l, Decl(spreadOverwritesPropertyStrict.ts, 24, 1)) +>anyrequired : Symbol(anyrequired, Decl(spreadOverwritesPropertyStrict.ts, 26, 11)) +>a : Symbol(a, Decl(spreadOverwritesPropertyStrict.ts, 26, 25)) + + return { a: 'zzz', ...anyrequired } // error +>a : Symbol(a, Decl(spreadOverwritesPropertyStrict.ts, 27, 12)) +>anyrequired : Symbol(anyrequired, Decl(spreadOverwritesPropertyStrict.ts, 26, 11)) +} +function m(anyoptional: { a?: any }) { +>m : Symbol(m, Decl(spreadOverwritesPropertyStrict.ts, 28, 1)) +>anyoptional : Symbol(anyoptional, Decl(spreadOverwritesPropertyStrict.ts, 29, 11)) +>a : Symbol(a, Decl(spreadOverwritesPropertyStrict.ts, 29, 25)) + + return { a: 'zzz', ...anyoptional } // ok +>a : Symbol(a, Decl(spreadOverwritesPropertyStrict.ts, 30, 12)) +>anyoptional : Symbol(anyoptional, Decl(spreadOverwritesPropertyStrict.ts, 29, 11)) +} + + diff --git a/tests/baselines/reference/spreadOverwritesPropertyStrict.types b/tests/baselines/reference/spreadOverwritesPropertyStrict.types index 72be86e2c6dd7..cf4e022eb35b5 100644 --- a/tests/baselines/reference/spreadOverwritesPropertyStrict.types +++ b/tests/baselines/reference/spreadOverwritesPropertyStrict.types @@ -124,3 +124,27 @@ function k(t: { command: string, ok: string }) { >t : { command: string; ok: string; } } +function l(anyrequired: { a: any }) { +>l : (anyrequired: { a: any;}) => { a: any; } +>anyrequired : { a: any; } +>a : any + + return { a: 'zzz', ...anyrequired } // error +>{ a: 'zzz', ...anyrequired } : { a: any; } +>a : string +>'zzz' : "zzz" +>anyrequired : { a: any; } +} +function m(anyoptional: { a?: any }) { +>m : (anyoptional: { a?: any;}) => { a: any; } +>anyoptional : { a?: any; } +>a : any + + return { a: 'zzz', ...anyoptional } // ok +>{ a: 'zzz', ...anyoptional } : { a: any; } +>a : string +>'zzz' : "zzz" +>anyoptional : { a?: any; } +} + + diff --git a/tests/cases/conformance/types/spread/spreadOverwritesPropertyStrict.ts b/tests/cases/conformance/types/spread/spreadOverwritesPropertyStrict.ts index 2f90accf42142..80603e9daa0b5 100644 --- a/tests/cases/conformance/types/spread/spreadOverwritesPropertyStrict.ts +++ b/tests/cases/conformance/types/spread/spreadOverwritesPropertyStrict.ts @@ -24,3 +24,11 @@ function j() { function k(t: { command: string, ok: string }) { return { command: "hi", ...{ spoiler: true }, spoiler2: true, ...t } // error } + +function l(anyrequired: { a: any }) { + return { a: 'zzz', ...anyrequired } // error +} +function m(anyoptional: { a?: any }) { + return { a: 'zzz', ...anyoptional } // ok +} +