diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 64e7ca0a8164a..903e2aac0feba 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -709,6 +709,7 @@ import { isRequireCall, isRestParameter, isRestTypeNode, + isReturnStatement, isRightSideOfAccessExpression, isRightSideOfInstanceofExpression, isRightSideOfQualifiedNameOrPropertyAccess, @@ -22294,8 +22295,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { reducedTarget = findMatchingDiscriminantType(source, target as UnionType, isRelatedTo) || filterPrimitivesIfContainsNonPrimitive(target as UnionType); checkTypes = reducedTarget.flags & TypeFlags.Union ? (reducedTarget as UnionType).types : [reducedTarget]; } + + const containerDecl = source.symbol.valueDeclaration; + if (containerDecl === undefined) return false; + + // we accept extra EPC cases when #59277 + const isValidParent = (n: Node) => { + return hasOnlyExpressionInitializer(n) || isSatisfiesExpression(n) || isReturnStatement(n); + }; + const checkSpread = isObjectLiteralExpression(containerDecl) && isValidParent(containerDecl.parent) && + findAncestor(containerDecl.parent, n => { + if (isSourceFile(n)) return "quit"; + return isJsxOpeningLikeElement(n); + }) === undefined; + for (const prop of getPropertiesOfType(source)) { - if (shouldCheckAsExcessProperty(prop, source.symbol) && !isIgnoredJsxProperty(source, prop)) { + if (shouldCheckAsExcessProperty(prop) && !isIgnoredJsxProperty(source, prop)) { if (!isKnownProperty(reducedTarget, prop.escapedName, isComparingJsxAttributes)) { if (reportErrors) { // Report error in terms of object types in the target as those are the only ones @@ -22357,10 +22372,27 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } return false; - } - function shouldCheckAsExcessProperty(prop: Symbol, container: Symbol) { - return prop.valueDeclaration && container.valueDeclaration && prop.valueDeclaration.parent === container.valueDeclaration; + function shouldCheckAsExcessProperty(prop: Symbol) { + if (prop.valueDeclaration?.parent === containerDecl) return true; + if (!checkSpread) return false; + if (prop.declarations) return prop.declarations.some(isPropFromInlineSpread); + return false; + + function isPropFromInlineSpread(d: Declaration) { + return isObjectLiteralExpression(d.parent) && findAncestor(d.parent, n => { + if (n === containerDecl || isSourceFile(n.parent.parent)) return "quit"; + if ( + isSpreadAssignment(n.parent) + && isObjectLiteralExpression(n.parent.parent) + && n.parent.parent === containerDecl + ) { + return true; + } + return false; + }); + } + } } function unionOrIntersectionRelatedTo(source: Type, target: Type, reportErrors: boolean, intersectionState: IntersectionState): Ternary { diff --git a/tests/baselines/reference/excessPropertyCheckInlineChainedConditional.errors.txt b/tests/baselines/reference/excessPropertyCheckInlineChainedConditional.errors.txt new file mode 100644 index 0000000000000..8d8c7b85d9000 --- /dev/null +++ b/tests/baselines/reference/excessPropertyCheckInlineChainedConditional.errors.txt @@ -0,0 +1,55 @@ +excessPropertyCheckInlineChainedConditional.ts(13,17): error TS2322: Type '{ bar: number; excessPropertyA: string; foo: number; } | { bar: number; excessPropertyB: string; foo: number; } | { bar: number; foo: number; } | { foo: number; excessPropertyC: string; } | { foo: number; } | { excessPropertyD: string; foo: number; }' is not assignable to type 'MyObj'. + Object literal may only specify known properties, and 'excessPropertyA' does not exist in type 'MyObj'. + + +==== excessPropertyCheckInlineChainedConditional.ts (1 errors) ==== + declare const someConditions: boolean[]; + // bar is optional + type MyObj = { foo: number; bar?: number }; + const yWithExtraProp = { Y: 2 }; + const zWithExtraProp = { Z: 2, excessPropertyZ: "Z" }; + + const v1: MyObj = { + foo: 1, + ...(someConditions[0] + ? someConditions[1] + ? { + bar: 2, + excessPropertyA: "A", + ~~~~~~~~~~~~~~~ +!!! error TS2322: Type '{ bar: number; excessPropertyA: string; foo: number; } | { bar: number; excessPropertyB: string; foo: number; } | { bar: number; foo: number; } | { foo: number; excessPropertyC: string; } | { foo: number; } | { excessPropertyD: string; foo: number; }' is not assignable to type 'MyObj'. +!!! error TS2322: Object literal may only specify known properties, and 'excessPropertyA' does not exist in type 'MyObj'. + } + : someConditions[2] + ? someConditions[3] + ? { + bar: 2, + excessPropertyB: "B", + } + : { bar: 2 } + : someConditions[4] + ? { + foo: 2, + excessPropertyC: "C", + } + : {} + : { excessPropertyD: "D" }), + }; + + // no errors by design since the objects are not defined inline + const v2: MyObj = { + ...(someConditions[0] + ? someConditions[1] + ? { bar: 2 } + : someConditions[2] + ? someConditions[3] + ? yWithExtraProp + : { bar: 2 } + : someConditions[4] + ? { foo: 2 } + : {} + : zWithExtraProp), + foo: 1, + }; + + \ No newline at end of file diff --git a/tests/baselines/reference/excessPropertyCheckInlineChainedConditional.symbols b/tests/baselines/reference/excessPropertyCheckInlineChainedConditional.symbols new file mode 100644 index 0000000000000..364414a075262 --- /dev/null +++ b/tests/baselines/reference/excessPropertyCheckInlineChainedConditional.symbols @@ -0,0 +1,115 @@ +//// [tests/cases/compiler/excessPropertyCheckInlineChainedConditional.ts] //// + +=== excessPropertyCheckInlineChainedConditional.ts === +declare const someConditions: boolean[]; +>someConditions : Symbol(someConditions, Decl(excessPropertyCheckInlineChainedConditional.ts, 0, 13)) + +// bar is optional +type MyObj = { foo: number; bar?: number }; +>MyObj : Symbol(MyObj, Decl(excessPropertyCheckInlineChainedConditional.ts, 0, 40)) +>foo : Symbol(foo, Decl(excessPropertyCheckInlineChainedConditional.ts, 2, 14)) +>bar : Symbol(bar, Decl(excessPropertyCheckInlineChainedConditional.ts, 2, 27)) + +const yWithExtraProp = { Y: 2 }; +>yWithExtraProp : Symbol(yWithExtraProp, Decl(excessPropertyCheckInlineChainedConditional.ts, 3, 5)) +>Y : Symbol(Y, Decl(excessPropertyCheckInlineChainedConditional.ts, 3, 24)) + +const zWithExtraProp = { Z: 2, excessPropertyZ: "Z" }; +>zWithExtraProp : Symbol(zWithExtraProp, Decl(excessPropertyCheckInlineChainedConditional.ts, 4, 5)) +>Z : Symbol(Z, Decl(excessPropertyCheckInlineChainedConditional.ts, 4, 24)) +>excessPropertyZ : Symbol(excessPropertyZ, Decl(excessPropertyCheckInlineChainedConditional.ts, 4, 30)) + +const v1: MyObj = { +>v1 : Symbol(v1, Decl(excessPropertyCheckInlineChainedConditional.ts, 6, 5)) +>MyObj : Symbol(MyObj, Decl(excessPropertyCheckInlineChainedConditional.ts, 0, 40)) + + foo: 1, +>foo : Symbol(foo, Decl(excessPropertyCheckInlineChainedConditional.ts, 6, 19)) + + ...(someConditions[0] +>someConditions : Symbol(someConditions, Decl(excessPropertyCheckInlineChainedConditional.ts, 0, 13)) + + ? someConditions[1] +>someConditions : Symbol(someConditions, Decl(excessPropertyCheckInlineChainedConditional.ts, 0, 13)) + + ? { + bar: 2, +>bar : Symbol(bar, Decl(excessPropertyCheckInlineChainedConditional.ts, 10, 15)) + + excessPropertyA: "A", +>excessPropertyA : Symbol(excessPropertyA, Decl(excessPropertyCheckInlineChainedConditional.ts, 11, 23)) + } + : someConditions[2] +>someConditions : Symbol(someConditions, Decl(excessPropertyCheckInlineChainedConditional.ts, 0, 13)) + + ? someConditions[3] +>someConditions : Symbol(someConditions, Decl(excessPropertyCheckInlineChainedConditional.ts, 0, 13)) + + ? { + bar: 2, +>bar : Symbol(bar, Decl(excessPropertyCheckInlineChainedConditional.ts, 16, 23)) + + excessPropertyB: "B", +>excessPropertyB : Symbol(excessPropertyB, Decl(excessPropertyCheckInlineChainedConditional.ts, 17, 31)) + } + : { bar: 2 } +>bar : Symbol(bar, Decl(excessPropertyCheckInlineChainedConditional.ts, 20, 23)) + + : someConditions[4] +>someConditions : Symbol(someConditions, Decl(excessPropertyCheckInlineChainedConditional.ts, 0, 13)) + + ? { + foo: 2, +>foo : Symbol(foo, Decl(excessPropertyCheckInlineChainedConditional.ts, 22, 15)) + + excessPropertyC: "C", +>excessPropertyC : Symbol(excessPropertyC, Decl(excessPropertyCheckInlineChainedConditional.ts, 23, 23)) + } + : {} + : { excessPropertyD: "D" }), +>excessPropertyD : Symbol(excessPropertyD, Decl(excessPropertyCheckInlineChainedConditional.ts, 27, 11)) + +}; + +// no errors by design since the objects are not defined inline +const v2: MyObj = { +>v2 : Symbol(v2, Decl(excessPropertyCheckInlineChainedConditional.ts, 31, 5)) +>MyObj : Symbol(MyObj, Decl(excessPropertyCheckInlineChainedConditional.ts, 0, 40)) + + ...(someConditions[0] +>someConditions : Symbol(someConditions, Decl(excessPropertyCheckInlineChainedConditional.ts, 0, 13)) + + ? someConditions[1] +>someConditions : Symbol(someConditions, Decl(excessPropertyCheckInlineChainedConditional.ts, 0, 13)) + + ? { bar: 2 } +>bar : Symbol(bar, Decl(excessPropertyCheckInlineChainedConditional.ts, 34, 15)) + + : someConditions[2] +>someConditions : Symbol(someConditions, Decl(excessPropertyCheckInlineChainedConditional.ts, 0, 13)) + + ? someConditions[3] +>someConditions : Symbol(someConditions, Decl(excessPropertyCheckInlineChainedConditional.ts, 0, 13)) + + ? yWithExtraProp +>yWithExtraProp : Symbol(yWithExtraProp, Decl(excessPropertyCheckInlineChainedConditional.ts, 3, 5)) + + : { bar: 2 } +>bar : Symbol(bar, Decl(excessPropertyCheckInlineChainedConditional.ts, 38, 23)) + + : someConditions[4] +>someConditions : Symbol(someConditions, Decl(excessPropertyCheckInlineChainedConditional.ts, 0, 13)) + + ? { foo: 2 } +>foo : Symbol(foo, Decl(excessPropertyCheckInlineChainedConditional.ts, 40, 15)) + + : {} + : zWithExtraProp), +>zWithExtraProp : Symbol(zWithExtraProp, Decl(excessPropertyCheckInlineChainedConditional.ts, 4, 5)) + + foo: 1, +>foo : Symbol(foo, Decl(excessPropertyCheckInlineChainedConditional.ts, 42, 26)) + +}; + + diff --git a/tests/baselines/reference/excessPropertyCheckInlineChainedConditional.types b/tests/baselines/reference/excessPropertyCheckInlineChainedConditional.types new file mode 100644 index 0000000000000..d0eb43acebdd3 --- /dev/null +++ b/tests/baselines/reference/excessPropertyCheckInlineChainedConditional.types @@ -0,0 +1,278 @@ +//// [tests/cases/compiler/excessPropertyCheckInlineChainedConditional.ts] //// + +=== excessPropertyCheckInlineChainedConditional.ts === +declare const someConditions: boolean[]; +>someConditions : boolean[] +> : ^^^^^^^^^ + +// bar is optional +type MyObj = { foo: number; bar?: number }; +>MyObj : MyObj +> : ^^^^^ +>foo : number +> : ^^^^^^ +>bar : number | undefined +> : ^^^^^^^^^^^^^^^^^^ + +const yWithExtraProp = { Y: 2 }; +>yWithExtraProp : { Y: number; } +> : ^^^^^^^^^^^^^^ +>{ Y: 2 } : { Y: number; } +> : ^^^^^^^^^^^^^^ +>Y : number +> : ^^^^^^ +>2 : 2 +> : ^ + +const zWithExtraProp = { Z: 2, excessPropertyZ: "Z" }; +>zWithExtraProp : { Z: number; excessPropertyZ: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ Z: 2, excessPropertyZ: "Z" } : { Z: number; excessPropertyZ: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>Z : number +> : ^^^^^^ +>2 : 2 +> : ^ +>excessPropertyZ : string +> : ^^^^^^ +>"Z" : "Z" +> : ^^^ + +const v1: MyObj = { +>v1 : MyObj +> : ^^^^^ +>{ foo: 1, ...(someConditions[0] ? someConditions[1] ? { bar: 2, excessPropertyA: "A", } : someConditions[2] ? someConditions[3] ? { bar: 2, excessPropertyB: "B", } : { bar: 2 } : someConditions[4] ? { foo: 2, excessPropertyC: "C", } : {} : { excessPropertyD: "D" }),} : { bar: number; excessPropertyA: string; foo: number; } | { bar: number; excessPropertyB: string; foo: number; } | { bar: number; foo: number; } | { foo: number; excessPropertyC: string; } | { foo: number; } | { excessPropertyD: string; foo: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + foo: 1, +>foo : number +> : ^^^^^^ +>1 : 1 +> : ^ + + ...(someConditions[0] +>(someConditions[0] ? someConditions[1] ? { bar: 2, excessPropertyA: "A", } : someConditions[2] ? someConditions[3] ? { bar: 2, excessPropertyB: "B", } : { bar: 2 } : someConditions[4] ? { foo: 2, excessPropertyC: "C", } : {} : { excessPropertyD: "D" }) : { bar: number; excessPropertyA: string; } | { bar: number; excessPropertyB: string; } | { bar: number; } | { foo: number; excessPropertyC: string; } | {} | { excessPropertyD: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>someConditions[0] ? someConditions[1] ? { bar: 2, excessPropertyA: "A", } : someConditions[2] ? someConditions[3] ? { bar: 2, excessPropertyB: "B", } : { bar: 2 } : someConditions[4] ? { foo: 2, excessPropertyC: "C", } : {} : { excessPropertyD: "D" } : { bar: number; excessPropertyA: string; } | { bar: number; excessPropertyB: string; } | { bar: number; } | { foo: number; excessPropertyC: string; } | {} | { excessPropertyD: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>someConditions[0] : boolean +> : ^^^^^^^ +>someConditions : boolean[] +> : ^^^^^^^^^ +>0 : 0 +> : ^ + + ? someConditions[1] +>someConditions[1] ? { bar: 2, excessPropertyA: "A", } : someConditions[2] ? someConditions[3] ? { bar: 2, excessPropertyB: "B", } : { bar: 2 } : someConditions[4] ? { foo: 2, excessPropertyC: "C", } : {} : { bar: number; excessPropertyA: string; } | { bar: number; excessPropertyB: string; } | { bar: number; } | { foo: number; excessPropertyC: string; } | {} +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>someConditions[1] : boolean +> : ^^^^^^^ +>someConditions : boolean[] +> : ^^^^^^^^^ +>1 : 1 +> : ^ + + ? { +>{ bar: 2, excessPropertyA: "A", } : { bar: number; excessPropertyA: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + bar: 2, +>bar : number +> : ^^^^^^ +>2 : 2 +> : ^ + + excessPropertyA: "A", +>excessPropertyA : string +> : ^^^^^^ +>"A" : "A" +> : ^^^ + } + : someConditions[2] +>someConditions[2] ? someConditions[3] ? { bar: 2, excessPropertyB: "B", } : { bar: 2 } : someConditions[4] ? { foo: 2, excessPropertyC: "C", } : {} : { bar: number; excessPropertyB: string; } | { bar: number; } | { foo: number; excessPropertyC: string; } | {} +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>someConditions[2] : boolean +> : ^^^^^^^ +>someConditions : boolean[] +> : ^^^^^^^^^ +>2 : 2 +> : ^ + + ? someConditions[3] +>someConditions[3] ? { bar: 2, excessPropertyB: "B", } : { bar: 2 } : { bar: number; excessPropertyB: string; } | { bar: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>someConditions[3] : boolean +> : ^^^^^^^ +>someConditions : boolean[] +> : ^^^^^^^^^ +>3 : 3 +> : ^ + + ? { +>{ bar: 2, excessPropertyB: "B", } : { bar: number; excessPropertyB: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + bar: 2, +>bar : number +> : ^^^^^^ +>2 : 2 +> : ^ + + excessPropertyB: "B", +>excessPropertyB : string +> : ^^^^^^ +>"B" : "B" +> : ^^^ + } + : { bar: 2 } +>{ bar: 2 } : { bar: number; } +> : ^^^^^^^^^^^^^^^^ +>bar : number +> : ^^^^^^ +>2 : 2 +> : ^ + + : someConditions[4] +>someConditions[4] ? { foo: 2, excessPropertyC: "C", } : {} : { foo: number; excessPropertyC: string; } | {} +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>someConditions[4] : boolean +> : ^^^^^^^ +>someConditions : boolean[] +> : ^^^^^^^^^ +>4 : 4 +> : ^ + + ? { +>{ foo: 2, excessPropertyC: "C", } : { foo: number; excessPropertyC: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + foo: 2, +>foo : number +> : ^^^^^^ +>2 : 2 +> : ^ + + excessPropertyC: "C", +>excessPropertyC : string +> : ^^^^^^ +>"C" : "C" +> : ^^^ + } + : {} +>{} : {} +> : ^^ + + : { excessPropertyD: "D" }), +>{ excessPropertyD: "D" } : { excessPropertyD: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>excessPropertyD : string +> : ^^^^^^ +>"D" : "D" +> : ^^^ + +}; + +// no errors by design since the objects are not defined inline +const v2: MyObj = { +>v2 : MyObj +> : ^^^^^ +>{ ...(someConditions[0] ? someConditions[1] ? { bar: 2 } : someConditions[2] ? someConditions[3] ? yWithExtraProp : { bar: 2 } : someConditions[4] ? { foo: 2 } : {} : zWithExtraProp), foo: 1,} : { foo: number; Y: number; } | { foo: number; Z: number; excessPropertyZ: string; } | { foo: number; bar: number; } | { foo: number; } | { foo: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + ...(someConditions[0] +>(someConditions[0] ? someConditions[1] ? { bar: 2 } : someConditions[2] ? someConditions[3] ? yWithExtraProp : { bar: 2 } : someConditions[4] ? { foo: 2 } : {} : zWithExtraProp) : { Y: number; } | { Z: number; excessPropertyZ: string; } | { bar: number; } | { foo: number; } | {} +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>someConditions[0] ? someConditions[1] ? { bar: 2 } : someConditions[2] ? someConditions[3] ? yWithExtraProp : { bar: 2 } : someConditions[4] ? { foo: 2 } : {} : zWithExtraProp : { Y: number; } | { Z: number; excessPropertyZ: string; } | { bar: number; } | { foo: number; } | {} +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>someConditions[0] : boolean +> : ^^^^^^^ +>someConditions : boolean[] +> : ^^^^^^^^^ +>0 : 0 +> : ^ + + ? someConditions[1] +>someConditions[1] ? { bar: 2 } : someConditions[2] ? someConditions[3] ? yWithExtraProp : { bar: 2 } : someConditions[4] ? { foo: 2 } : {} : { Y: number; } | { bar: number; } | { foo: number; } | {} +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>someConditions[1] : boolean +> : ^^^^^^^ +>someConditions : boolean[] +> : ^^^^^^^^^ +>1 : 1 +> : ^ + + ? { bar: 2 } +>{ bar: 2 } : { bar: number; } +> : ^^^^^^^^^^^^^^^^ +>bar : number +> : ^^^^^^ +>2 : 2 +> : ^ + + : someConditions[2] +>someConditions[2] ? someConditions[3] ? yWithExtraProp : { bar: 2 } : someConditions[4] ? { foo: 2 } : {} : { Y: number; } | { bar: number; } | { foo: number; } | {} +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>someConditions[2] : boolean +> : ^^^^^^^ +>someConditions : boolean[] +> : ^^^^^^^^^ +>2 : 2 +> : ^ + + ? someConditions[3] +>someConditions[3] ? yWithExtraProp : { bar: 2 } : { Y: number; } | { bar: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>someConditions[3] : boolean +> : ^^^^^^^ +>someConditions : boolean[] +> : ^^^^^^^^^ +>3 : 3 +> : ^ + + ? yWithExtraProp +>yWithExtraProp : { Y: number; } +> : ^^^^^^^^^^^^^^ + + : { bar: 2 } +>{ bar: 2 } : { bar: number; } +> : ^^^^^^^^^^^^^^^^ +>bar : number +> : ^^^^^^ +>2 : 2 +> : ^ + + : someConditions[4] +>someConditions[4] ? { foo: 2 } : {} : { foo: number; } | {} +> : ^^^^^^^^^^^^^^^^^^^^^ +>someConditions[4] : boolean +> : ^^^^^^^ +>someConditions : boolean[] +> : ^^^^^^^^^ +>4 : 4 +> : ^ + + ? { foo: 2 } +>{ foo: 2 } : { foo: number; } +> : ^^^^^^^^^^^^^^^^ +>foo : number +> : ^^^^^^ +>2 : 2 +> : ^ + + : {} +>{} : {} +> : ^^ + + : zWithExtraProp), +>zWithExtraProp : { Z: number; excessPropertyZ: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + foo: 1, +>foo : number +> : ^^^^^^ +>1 : 1 +> : ^ + +}; + + diff --git a/tests/baselines/reference/excessPropertyCheckInlineObjectWithSpreadVariable.errors.txt b/tests/baselines/reference/excessPropertyCheckInlineObjectWithSpreadVariable.errors.txt new file mode 100644 index 0000000000000..073b0d965af8d --- /dev/null +++ b/tests/baselines/reference/excessPropertyCheckInlineObjectWithSpreadVariable.errors.txt @@ -0,0 +1,37 @@ +excessPropertyCheckInlineObjectWithSpreadVariable.ts(11,20): error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type 'Foo'. +excessPropertyCheckInlineObjectWithSpreadVariable.ts(14,26): error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type 'Foo'. +excessPropertyCheckInlineObjectWithSpreadVariable.ts(18,21): error TS2353: Object literal may only specify known properties, and 'extraProp2' does not exist in type 'Foo'. +excessPropertyCheckInlineObjectWithSpreadVariable.ts(21,26): error TS2353: Object literal may only specify known properties, and 'noBar' does not exist in type 'Foo'. + + +==== excessPropertyCheckInlineObjectWithSpreadVariable.ts (4 errors) ==== + type Foo = { + foo: string; + } + + type Bar = { + extraProp: string; + } + + const bar: Bar = { extraProp: "" }; + + const foo: Foo = { bar: "", foo: "" }; + ~~~ +!!! error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type 'Foo'. + const foo2: Foo = { ...bar, foo: "" }; + const foo3: Foo = { ...{ ...bar}, foo: ""}; + const foo4: Foo = { ...{ bar: "" }, foo: ""}; + ~~~ +!!! error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type 'Foo'. + + + const noBar = { extraProp2: "" }; + const foo5: Foo = { extraProp2: "", foo: "" }; + ~~~~~~~~~~ +!!! error TS2353: Object literal may only specify known properties, and 'extraProp2' does not exist in type 'Foo'. + const foo6: Foo = { ...noBar, foo: "" }; + const foo7: Foo = { ...{ ...noBar}, foo: ""}; + const foo8: Foo = { ...{ noBar: "" }, foo: ""}; + ~~~~~ +!!! error TS2353: Object literal may only specify known properties, and 'noBar' does not exist in type 'Foo'. + \ No newline at end of file diff --git a/tests/baselines/reference/excessPropertyCheckInlineObjectWithSpreadVariable.symbols b/tests/baselines/reference/excessPropertyCheckInlineObjectWithSpreadVariable.symbols new file mode 100644 index 0000000000000..c58fecaa202d7 --- /dev/null +++ b/tests/baselines/reference/excessPropertyCheckInlineObjectWithSpreadVariable.symbols @@ -0,0 +1,75 @@ +//// [tests/cases/compiler/excessPropertyCheckInlineObjectWithSpreadVariable.ts] //// + +=== excessPropertyCheckInlineObjectWithSpreadVariable.ts === +type Foo = { +>Foo : Symbol(Foo, Decl(excessPropertyCheckInlineObjectWithSpreadVariable.ts, 0, 0)) + + foo: string; +>foo : Symbol(foo, Decl(excessPropertyCheckInlineObjectWithSpreadVariable.ts, 0, 12)) +} + +type Bar = { +>Bar : Symbol(Bar, Decl(excessPropertyCheckInlineObjectWithSpreadVariable.ts, 2, 1)) + + extraProp: string; +>extraProp : Symbol(extraProp, Decl(excessPropertyCheckInlineObjectWithSpreadVariable.ts, 4, 12)) +} + +const bar: Bar = { extraProp: "" }; +>bar : Symbol(bar, Decl(excessPropertyCheckInlineObjectWithSpreadVariable.ts, 8, 5)) +>Bar : Symbol(Bar, Decl(excessPropertyCheckInlineObjectWithSpreadVariable.ts, 2, 1)) +>extraProp : Symbol(extraProp, Decl(excessPropertyCheckInlineObjectWithSpreadVariable.ts, 8, 18)) + +const foo: Foo = { bar: "", foo: "" }; +>foo : Symbol(foo, Decl(excessPropertyCheckInlineObjectWithSpreadVariable.ts, 10, 5)) +>Foo : Symbol(Foo, Decl(excessPropertyCheckInlineObjectWithSpreadVariable.ts, 0, 0)) +>bar : Symbol(bar, Decl(excessPropertyCheckInlineObjectWithSpreadVariable.ts, 10, 18)) +>foo : Symbol(foo, Decl(excessPropertyCheckInlineObjectWithSpreadVariable.ts, 10, 27)) + +const foo2: Foo = { ...bar, foo: "" }; +>foo2 : Symbol(foo2, Decl(excessPropertyCheckInlineObjectWithSpreadVariable.ts, 11, 5)) +>Foo : Symbol(Foo, Decl(excessPropertyCheckInlineObjectWithSpreadVariable.ts, 0, 0)) +>bar : Symbol(bar, Decl(excessPropertyCheckInlineObjectWithSpreadVariable.ts, 8, 5)) +>foo : Symbol(foo, Decl(excessPropertyCheckInlineObjectWithSpreadVariable.ts, 11, 27)) + +const foo3: Foo = { ...{ ...bar}, foo: ""}; +>foo3 : Symbol(foo3, Decl(excessPropertyCheckInlineObjectWithSpreadVariable.ts, 12, 5)) +>Foo : Symbol(Foo, Decl(excessPropertyCheckInlineObjectWithSpreadVariable.ts, 0, 0)) +>bar : Symbol(bar, Decl(excessPropertyCheckInlineObjectWithSpreadVariable.ts, 8, 5)) +>foo : Symbol(foo, Decl(excessPropertyCheckInlineObjectWithSpreadVariable.ts, 12, 33)) + +const foo4: Foo = { ...{ bar: "" }, foo: ""}; +>foo4 : Symbol(foo4, Decl(excessPropertyCheckInlineObjectWithSpreadVariable.ts, 13, 5)) +>Foo : Symbol(Foo, Decl(excessPropertyCheckInlineObjectWithSpreadVariable.ts, 0, 0)) +>bar : Symbol(bar, Decl(excessPropertyCheckInlineObjectWithSpreadVariable.ts, 13, 24)) +>foo : Symbol(foo, Decl(excessPropertyCheckInlineObjectWithSpreadVariable.ts, 13, 35)) + + +const noBar = { extraProp2: "" }; +>noBar : Symbol(noBar, Decl(excessPropertyCheckInlineObjectWithSpreadVariable.ts, 16, 5)) +>extraProp2 : Symbol(extraProp2, Decl(excessPropertyCheckInlineObjectWithSpreadVariable.ts, 16, 15)) + +const foo5: Foo = { extraProp2: "", foo: "" }; +>foo5 : Symbol(foo5, Decl(excessPropertyCheckInlineObjectWithSpreadVariable.ts, 17, 5)) +>Foo : Symbol(Foo, Decl(excessPropertyCheckInlineObjectWithSpreadVariable.ts, 0, 0)) +>extraProp2 : Symbol(extraProp2, Decl(excessPropertyCheckInlineObjectWithSpreadVariable.ts, 17, 19)) +>foo : Symbol(foo, Decl(excessPropertyCheckInlineObjectWithSpreadVariable.ts, 17, 35)) + +const foo6: Foo = { ...noBar, foo: "" }; +>foo6 : Symbol(foo6, Decl(excessPropertyCheckInlineObjectWithSpreadVariable.ts, 18, 5)) +>Foo : Symbol(Foo, Decl(excessPropertyCheckInlineObjectWithSpreadVariable.ts, 0, 0)) +>noBar : Symbol(noBar, Decl(excessPropertyCheckInlineObjectWithSpreadVariable.ts, 16, 5)) +>foo : Symbol(foo, Decl(excessPropertyCheckInlineObjectWithSpreadVariable.ts, 18, 29)) + +const foo7: Foo = { ...{ ...noBar}, foo: ""}; +>foo7 : Symbol(foo7, Decl(excessPropertyCheckInlineObjectWithSpreadVariable.ts, 19, 5)) +>Foo : Symbol(Foo, Decl(excessPropertyCheckInlineObjectWithSpreadVariable.ts, 0, 0)) +>noBar : Symbol(noBar, Decl(excessPropertyCheckInlineObjectWithSpreadVariable.ts, 16, 5)) +>foo : Symbol(foo, Decl(excessPropertyCheckInlineObjectWithSpreadVariable.ts, 19, 35)) + +const foo8: Foo = { ...{ noBar: "" }, foo: ""}; +>foo8 : Symbol(foo8, Decl(excessPropertyCheckInlineObjectWithSpreadVariable.ts, 20, 5)) +>Foo : Symbol(Foo, Decl(excessPropertyCheckInlineObjectWithSpreadVariable.ts, 0, 0)) +>noBar : Symbol(noBar, Decl(excessPropertyCheckInlineObjectWithSpreadVariable.ts, 20, 24)) +>foo : Symbol(foo, Decl(excessPropertyCheckInlineObjectWithSpreadVariable.ts, 20, 37)) + diff --git a/tests/baselines/reference/excessPropertyCheckInlineObjectWithSpreadVariable.types b/tests/baselines/reference/excessPropertyCheckInlineObjectWithSpreadVariable.types new file mode 100644 index 0000000000000..f7c432baa4343 --- /dev/null +++ b/tests/baselines/reference/excessPropertyCheckInlineObjectWithSpreadVariable.types @@ -0,0 +1,154 @@ +//// [tests/cases/compiler/excessPropertyCheckInlineObjectWithSpreadVariable.ts] //// + +=== excessPropertyCheckInlineObjectWithSpreadVariable.ts === +type Foo = { +>Foo : Foo +> : ^^^ + + foo: string; +>foo : string +> : ^^^^^^ +} + +type Bar = { +>Bar : Bar +> : ^^^ + + extraProp: string; +>extraProp : string +> : ^^^^^^ +} + +const bar: Bar = { extraProp: "" }; +>bar : Bar +> : ^^^ +>{ extraProp: "" } : { extraProp: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^ +>extraProp : string +> : ^^^^^^ +>"" : "" +> : ^^ + +const foo: Foo = { bar: "", foo: "" }; +>foo : Foo +> : ^^^ +>{ bar: "", foo: "" } : { bar: string; foo: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>bar : string +> : ^^^^^^ +>"" : "" +> : ^^ +>foo : string +> : ^^^^^^ +>"" : "" +> : ^^ + +const foo2: Foo = { ...bar, foo: "" }; +>foo2 : Foo +> : ^^^ +>{ ...bar, foo: "" } : { foo: string; extraProp: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^ +>bar : Bar +> : ^^^ +>foo : string +> : ^^^^^^ +>"" : "" +> : ^^ + +const foo3: Foo = { ...{ ...bar}, foo: ""}; +>foo3 : Foo +> : ^^^ +>{ ...{ ...bar}, foo: ""} : { foo: string; extraProp: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^ +>{ ...bar} : { extraProp: string; } +> : ^^^^^^^^^^^^^ ^^^ +>bar : Bar +> : ^^^ +>foo : string +> : ^^^^^^ +>"" : "" +> : ^^ + +const foo4: Foo = { ...{ bar: "" }, foo: ""}; +>foo4 : Foo +> : ^^^ +>{ ...{ bar: "" }, foo: ""} : { foo: string; bar: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ bar: "" } : { bar: string; } +> : ^^^^^^^^^^^^^^^^ +>bar : string +> : ^^^^^^ +>"" : "" +> : ^^ +>foo : string +> : ^^^^^^ +>"" : "" +> : ^^ + + +const noBar = { extraProp2: "" }; +>noBar : { extraProp2: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^ +>{ extraProp2: "" } : { extraProp2: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^ +>extraProp2 : string +> : ^^^^^^ +>"" : "" +> : ^^ + +const foo5: Foo = { extraProp2: "", foo: "" }; +>foo5 : Foo +> : ^^^ +>{ extraProp2: "", foo: "" } : { extraProp2: string; foo: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>extraProp2 : string +> : ^^^^^^ +>"" : "" +> : ^^ +>foo : string +> : ^^^^^^ +>"" : "" +> : ^^ + +const foo6: Foo = { ...noBar, foo: "" }; +>foo6 : Foo +> : ^^^ +>{ ...noBar, foo: "" } : { foo: string; extraProp2: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>noBar : { extraProp2: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^ +>foo : string +> : ^^^^^^ +>"" : "" +> : ^^ + +const foo7: Foo = { ...{ ...noBar}, foo: ""}; +>foo7 : Foo +> : ^^^ +>{ ...{ ...noBar}, foo: ""} : { foo: string; extraProp2: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ ...noBar} : { extraProp2: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^ +>noBar : { extraProp2: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^ +>foo : string +> : ^^^^^^ +>"" : "" +> : ^^ + +const foo8: Foo = { ...{ noBar: "" }, foo: ""}; +>foo8 : Foo +> : ^^^ +>{ ...{ noBar: "" }, foo: ""} : { foo: string; noBar: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ noBar: "" } : { noBar: string; } +> : ^^^^^^^^^^^^^^^^^^ +>noBar : string +> : ^^^^^^ +>"" : "" +> : ^^ +>foo : string +> : ^^^^^^ +>"" : "" +> : ^^ + diff --git a/tests/baselines/reference/excessPropertyCheckSpreadConditionalInlineObject.errors.txt b/tests/baselines/reference/excessPropertyCheckSpreadConditionalInlineObject.errors.txt new file mode 100644 index 0000000000000..c34a70a42f708 --- /dev/null +++ b/tests/baselines/reference/excessPropertyCheckSpreadConditionalInlineObject.errors.txt @@ -0,0 +1,79 @@ +excessPropertyCheckSpreadConditionalInlineObject.ts(6,7): error TS2353: Object literal may only specify known properties, and 'excessProperty' does not exist in type 'C'. +excessPropertyCheckSpreadConditionalInlineObject.ts(24,3): error TS2353: Object literal may only specify known properties, and 'excessProperty' does not exist in type 'C'. +excessPropertyCheckSpreadConditionalInlineObject.ts(46,7): error TS2353: Object literal may only specify known properties, and 'excessProperty' does not exist in type 'D'. +excessPropertyCheckSpreadConditionalInlineObject.ts(64,3): error TS2353: Object literal may only specify known properties, and 'excessProperty' does not exist in type 'D'. + + +==== excessPropertyCheckSpreadConditionalInlineObject.ts (4 errors) ==== + declare const someCondition: boolean; + + // bar is optional + type C = { foo: number; bar?: number }; + + const c: C = { + ~ +!!! error TS2353: Object literal may only specify known properties, and 'excessProperty' does not exist in type 'C'. + foo: 1, + ...(someCondition + ? { + bar: 2, + excessProperty: 3, + } + : {}), + }; + + const c2 = { + foo: 1, + ...(someCondition + ? { + bar: 2, + excessProperty: 3, + } + : {}), + } satisfies C; + ~~~~~~~~~ +!!! error TS2353: Object literal may only specify known properties, and 'excessProperty' does not exist in type 'C'. + + function testC(condition: boolean) { + return someCondition ? { bar: 2, excessProperty: 3 } : {}; + } + + // no errors on c3 and c4 since not defined inline + const c3: C = { + foo: 1, + ...testC(someCondition) + }; + + const c4 = { + foo: 1, + ...testC(someCondition) + } satisfies C; + + + + // bar is not optional + type D = { foo: number; bar: number }; + + const d: D = { + ~ +!!! error TS2353: Object literal may only specify known properties, and 'excessProperty' does not exist in type 'D'. + foo: 1, + ...(someCondition + ? { + bar: 2, + excessProperty: 3, + } + : {}), + }; + + const d2 = { + foo: 1, + ...(someCondition + ? { + bar: 2, + excessProperty: 3, + } + : {}), + } satisfies D; + ~~~~~~~~~ +!!! error TS2353: Object literal may only specify known properties, and 'excessProperty' does not exist in type 'D'. \ No newline at end of file diff --git a/tests/baselines/reference/excessPropertyCheckSpreadConditionalInlineObject.symbols b/tests/baselines/reference/excessPropertyCheckSpreadConditionalInlineObject.symbols new file mode 100644 index 0000000000000..c08cddb4a8f08 --- /dev/null +++ b/tests/baselines/reference/excessPropertyCheckSpreadConditionalInlineObject.symbols @@ -0,0 +1,137 @@ +//// [tests/cases/compiler/excessPropertyCheckSpreadConditionalInlineObject.ts] //// + +=== excessPropertyCheckSpreadConditionalInlineObject.ts === +declare const someCondition: boolean; +>someCondition : Symbol(someCondition, Decl(excessPropertyCheckSpreadConditionalInlineObject.ts, 0, 13)) + +// bar is optional +type C = { foo: number; bar?: number }; +>C : Symbol(C, Decl(excessPropertyCheckSpreadConditionalInlineObject.ts, 0, 37)) +>foo : Symbol(foo, Decl(excessPropertyCheckSpreadConditionalInlineObject.ts, 3, 10)) +>bar : Symbol(bar, Decl(excessPropertyCheckSpreadConditionalInlineObject.ts, 3, 23)) + +const c: C = { +>c : Symbol(c, Decl(excessPropertyCheckSpreadConditionalInlineObject.ts, 5, 5)) +>C : Symbol(C, Decl(excessPropertyCheckSpreadConditionalInlineObject.ts, 0, 37)) + + foo: 1, +>foo : Symbol(foo, Decl(excessPropertyCheckSpreadConditionalInlineObject.ts, 5, 14)) + + ...(someCondition +>someCondition : Symbol(someCondition, Decl(excessPropertyCheckSpreadConditionalInlineObject.ts, 0, 13)) + + ? { + bar: 2, +>bar : Symbol(bar, Decl(excessPropertyCheckSpreadConditionalInlineObject.ts, 8, 11)) + + excessProperty: 3, +>excessProperty : Symbol(excessProperty, Decl(excessPropertyCheckSpreadConditionalInlineObject.ts, 9, 19)) + } + : {}), +}; + +const c2 = { +>c2 : Symbol(c2, Decl(excessPropertyCheckSpreadConditionalInlineObject.ts, 15, 5)) + + foo: 1, +>foo : Symbol(foo, Decl(excessPropertyCheckSpreadConditionalInlineObject.ts, 15, 12)) + + ...(someCondition +>someCondition : Symbol(someCondition, Decl(excessPropertyCheckSpreadConditionalInlineObject.ts, 0, 13)) + + ? { + bar: 2, +>bar : Symbol(bar, Decl(excessPropertyCheckSpreadConditionalInlineObject.ts, 18, 11)) + + excessProperty: 3, +>excessProperty : Symbol(excessProperty, Decl(excessPropertyCheckSpreadConditionalInlineObject.ts, 19, 19)) + } + : {}), +} satisfies C; +>C : Symbol(C, Decl(excessPropertyCheckSpreadConditionalInlineObject.ts, 0, 37)) + +function testC(condition: boolean) { +>testC : Symbol(testC, Decl(excessPropertyCheckSpreadConditionalInlineObject.ts, 23, 14)) +>condition : Symbol(condition, Decl(excessPropertyCheckSpreadConditionalInlineObject.ts, 25, 15)) + + return someCondition ? { bar: 2, excessProperty: 3 } : {}; +>someCondition : Symbol(someCondition, Decl(excessPropertyCheckSpreadConditionalInlineObject.ts, 0, 13)) +>bar : Symbol(bar, Decl(excessPropertyCheckSpreadConditionalInlineObject.ts, 26, 28)) +>excessProperty : Symbol(excessProperty, Decl(excessPropertyCheckSpreadConditionalInlineObject.ts, 26, 36)) +} + +// no errors on c3 and c4 since not defined inline +const c3: C = { +>c3 : Symbol(c3, Decl(excessPropertyCheckSpreadConditionalInlineObject.ts, 30, 5)) +>C : Symbol(C, Decl(excessPropertyCheckSpreadConditionalInlineObject.ts, 0, 37)) + + foo: 1, +>foo : Symbol(foo, Decl(excessPropertyCheckSpreadConditionalInlineObject.ts, 30, 15)) + + ...testC(someCondition) +>testC : Symbol(testC, Decl(excessPropertyCheckSpreadConditionalInlineObject.ts, 23, 14)) +>someCondition : Symbol(someCondition, Decl(excessPropertyCheckSpreadConditionalInlineObject.ts, 0, 13)) + +}; + +const c4 = { +>c4 : Symbol(c4, Decl(excessPropertyCheckSpreadConditionalInlineObject.ts, 35, 5)) + + foo: 1, +>foo : Symbol(foo, Decl(excessPropertyCheckSpreadConditionalInlineObject.ts, 35, 12)) + + ...testC(someCondition) +>testC : Symbol(testC, Decl(excessPropertyCheckSpreadConditionalInlineObject.ts, 23, 14)) +>someCondition : Symbol(someCondition, Decl(excessPropertyCheckSpreadConditionalInlineObject.ts, 0, 13)) + +} satisfies C; +>C : Symbol(C, Decl(excessPropertyCheckSpreadConditionalInlineObject.ts, 0, 37)) + + + +// bar is not optional +type D = { foo: number; bar: number }; +>D : Symbol(D, Decl(excessPropertyCheckSpreadConditionalInlineObject.ts, 38, 14)) +>foo : Symbol(foo, Decl(excessPropertyCheckSpreadConditionalInlineObject.ts, 43, 10)) +>bar : Symbol(bar, Decl(excessPropertyCheckSpreadConditionalInlineObject.ts, 43, 23)) + +const d: D = { +>d : Symbol(d, Decl(excessPropertyCheckSpreadConditionalInlineObject.ts, 45, 5)) +>D : Symbol(D, Decl(excessPropertyCheckSpreadConditionalInlineObject.ts, 38, 14)) + + foo: 1, +>foo : Symbol(foo, Decl(excessPropertyCheckSpreadConditionalInlineObject.ts, 45, 14)) + + ...(someCondition +>someCondition : Symbol(someCondition, Decl(excessPropertyCheckSpreadConditionalInlineObject.ts, 0, 13)) + + ? { + bar: 2, +>bar : Symbol(bar, Decl(excessPropertyCheckSpreadConditionalInlineObject.ts, 48, 11)) + + excessProperty: 3, +>excessProperty : Symbol(excessProperty, Decl(excessPropertyCheckSpreadConditionalInlineObject.ts, 49, 19)) + } + : {}), +}; + +const d2 = { +>d2 : Symbol(d2, Decl(excessPropertyCheckSpreadConditionalInlineObject.ts, 55, 5)) + + foo: 1, +>foo : Symbol(foo, Decl(excessPropertyCheckSpreadConditionalInlineObject.ts, 55, 12)) + + ...(someCondition +>someCondition : Symbol(someCondition, Decl(excessPropertyCheckSpreadConditionalInlineObject.ts, 0, 13)) + + ? { + bar: 2, +>bar : Symbol(bar, Decl(excessPropertyCheckSpreadConditionalInlineObject.ts, 58, 11)) + + excessProperty: 3, +>excessProperty : Symbol(excessProperty, Decl(excessPropertyCheckSpreadConditionalInlineObject.ts, 59, 19)) + } + : {}), +} satisfies D; +>D : Symbol(D, Decl(excessPropertyCheckSpreadConditionalInlineObject.ts, 38, 14)) + diff --git a/tests/baselines/reference/excessPropertyCheckSpreadConditionalInlineObject.types b/tests/baselines/reference/excessPropertyCheckSpreadConditionalInlineObject.types new file mode 100644 index 0000000000000..d0445656c5ce4 --- /dev/null +++ b/tests/baselines/reference/excessPropertyCheckSpreadConditionalInlineObject.types @@ -0,0 +1,270 @@ +//// [tests/cases/compiler/excessPropertyCheckSpreadConditionalInlineObject.ts] //// + +=== excessPropertyCheckSpreadConditionalInlineObject.ts === +declare const someCondition: boolean; +>someCondition : boolean +> : ^^^^^^^ + +// bar is optional +type C = { foo: number; bar?: number }; +>C : C +> : ^ +>foo : number +> : ^^^^^^ +>bar : number | undefined +> : ^^^^^^^^^^^^^^^^^^ + +const c: C = { +>c : C +> : ^ +>{ foo: 1, ...(someCondition ? { bar: 2, excessProperty: 3, } : {}),} : { bar?: number | undefined; excessProperty?: number | undefined; foo: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + foo: 1, +>foo : number +> : ^^^^^^ +>1 : 1 +> : ^ + + ...(someCondition +>(someCondition ? { bar: 2, excessProperty: 3, } : {}) : { bar: number; excessProperty: number; } | {} +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>someCondition ? { bar: 2, excessProperty: 3, } : {} : { bar: number; excessProperty: number; } | {} +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>someCondition : boolean +> : ^^^^^^^ + + ? { +>{ bar: 2, excessProperty: 3, } : { bar: number; excessProperty: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + bar: 2, +>bar : number +> : ^^^^^^ +>2 : 2 +> : ^ + + excessProperty: 3, +>excessProperty : number +> : ^^^^^^ +>3 : 3 +> : ^ + } + : {}), +>{} : {} +> : ^^ + +}; + +const c2 = { +>c2 : { bar?: number | undefined; excessProperty?: number | undefined; foo: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ foo: 1, ...(someCondition ? { bar: 2, excessProperty: 3, } : {}),} satisfies C : { bar?: number | undefined; excessProperty?: number | undefined; foo: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ foo: 1, ...(someCondition ? { bar: 2, excessProperty: 3, } : {}),} : { bar?: number | undefined; excessProperty?: number | undefined; foo: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + foo: 1, +>foo : number +> : ^^^^^^ +>1 : 1 +> : ^ + + ...(someCondition +>(someCondition ? { bar: 2, excessProperty: 3, } : {}) : { bar: number; excessProperty: number; } | {} +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>someCondition ? { bar: 2, excessProperty: 3, } : {} : { bar: number; excessProperty: number; } | {} +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>someCondition : boolean +> : ^^^^^^^ + + ? { +>{ bar: 2, excessProperty: 3, } : { bar: number; excessProperty: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + bar: 2, +>bar : number +> : ^^^^^^ +>2 : 2 +> : ^ + + excessProperty: 3, +>excessProperty : number +> : ^^^^^^ +>3 : 3 +> : ^ + } + : {}), +>{} : {} +> : ^^ + +} satisfies C; + +function testC(condition: boolean) { +>testC : (condition: boolean) => { bar: number; excessProperty: number; } | { bar?: undefined; excessProperty?: undefined; } +> : ^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>condition : boolean +> : ^^^^^^^ + + return someCondition ? { bar: 2, excessProperty: 3 } : {}; +>someCondition ? { bar: 2, excessProperty: 3 } : {} : { bar: number; excessProperty: number; } | {} +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>someCondition : boolean +> : ^^^^^^^ +>{ bar: 2, excessProperty: 3 } : { bar: number; excessProperty: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>bar : number +> : ^^^^^^ +>2 : 2 +> : ^ +>excessProperty : number +> : ^^^^^^ +>3 : 3 +> : ^ +>{} : {} +> : ^^ +} + +// no errors on c3 and c4 since not defined inline +const c3: C = { +>c3 : C +> : ^ +>{ foo: 1, ...testC(someCondition)} : { bar: number; excessProperty: number; foo: number; } | { bar?: undefined; excessProperty?: undefined; foo: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + foo: 1, +>foo : number +> : ^^^^^^ +>1 : 1 +> : ^ + + ...testC(someCondition) +>testC(someCondition) : { bar: number; excessProperty: number; } | { bar?: undefined; excessProperty?: undefined; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>testC : (condition: boolean) => { bar: number; excessProperty: number; } | { bar?: undefined; excessProperty?: undefined; } +> : ^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>someCondition : boolean +> : ^^^^^^^ + +}; + +const c4 = { +>c4 : { bar: number; excessProperty: number; foo: number; } | { bar?: undefined; excessProperty?: undefined; foo: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ foo: 1, ...testC(someCondition)} satisfies C : { bar: number; excessProperty: number; foo: number; } | { bar?: undefined; excessProperty?: undefined; foo: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ foo: 1, ...testC(someCondition)} : { bar: number; excessProperty: number; foo: number; } | { bar?: undefined; excessProperty?: undefined; foo: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + foo: 1, +>foo : number +> : ^^^^^^ +>1 : 1 +> : ^ + + ...testC(someCondition) +>testC(someCondition) : { bar: number; excessProperty: number; } | { bar?: undefined; excessProperty?: undefined; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>testC : (condition: boolean) => { bar: number; excessProperty: number; } | { bar?: undefined; excessProperty?: undefined; } +> : ^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>someCondition : boolean +> : ^^^^^^^ + +} satisfies C; + + + +// bar is not optional +type D = { foo: number; bar: number }; +>D : D +> : ^ +>foo : number +> : ^^^^^^ +>bar : number +> : ^^^^^^ + +const d: D = { +>d : D +> : ^ +>{ foo: 1, ...(someCondition ? { bar: 2, excessProperty: 3, } : {}),} : { bar?: number | undefined; excessProperty?: number | undefined; foo: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + foo: 1, +>foo : number +> : ^^^^^^ +>1 : 1 +> : ^ + + ...(someCondition +>(someCondition ? { bar: 2, excessProperty: 3, } : {}) : { bar: number; excessProperty: number; } | {} +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>someCondition ? { bar: 2, excessProperty: 3, } : {} : { bar: number; excessProperty: number; } | {} +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>someCondition : boolean +> : ^^^^^^^ + + ? { +>{ bar: 2, excessProperty: 3, } : { bar: number; excessProperty: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + bar: 2, +>bar : number +> : ^^^^^^ +>2 : 2 +> : ^ + + excessProperty: 3, +>excessProperty : number +> : ^^^^^^ +>3 : 3 +> : ^ + } + : {}), +>{} : {} +> : ^^ + +}; + +const d2 = { +>d2 : { bar?: number | undefined; excessProperty?: number | undefined; foo: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ foo: 1, ...(someCondition ? { bar: 2, excessProperty: 3, } : {}),} satisfies D : { bar?: number | undefined; excessProperty?: number | undefined; foo: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ foo: 1, ...(someCondition ? { bar: 2, excessProperty: 3, } : {}),} : { bar?: number | undefined; excessProperty?: number | undefined; foo: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + foo: 1, +>foo : number +> : ^^^^^^ +>1 : 1 +> : ^ + + ...(someCondition +>(someCondition ? { bar: 2, excessProperty: 3, } : {}) : { bar: number; excessProperty: number; } | {} +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>someCondition ? { bar: 2, excessProperty: 3, } : {} : { bar: number; excessProperty: number; } | {} +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>someCondition : boolean +> : ^^^^^^^ + + ? { +>{ bar: 2, excessProperty: 3, } : { bar: number; excessProperty: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + bar: 2, +>bar : number +> : ^^^^^^ +>2 : 2 +> : ^ + + excessProperty: 3, +>excessProperty : number +> : ^^^^^^ +>3 : 3 +> : ^ + } + : {}), +>{} : {} +> : ^^ + +} satisfies D; diff --git a/tests/baselines/reference/excessPropertyCheckSpreadFunctionParam.errors.txt b/tests/baselines/reference/excessPropertyCheckSpreadFunctionParam.errors.txt new file mode 100644 index 0000000000000..4d8dd36cf8590 --- /dev/null +++ b/tests/baselines/reference/excessPropertyCheckSpreadFunctionParam.errors.txt @@ -0,0 +1,54 @@ +excessPropertyCheckSpreadFunctionParam.ts(17,3): error TS2559: Type '{ c: number; }' has no properties in common with type 'Params'. +excessPropertyCheckSpreadFunctionParam.ts(27,3): error TS2559: Type '{ c: number; }' has no properties in common with type 'Params'. +excessPropertyCheckSpreadFunctionParam.ts(28,3): error TS2559: Type '{ c: number; }' has no properties in common with type 'Params'. +excessPropertyCheckSpreadFunctionParam.ts(30,3): error TS2559: Type '{ c: number; }' has no properties in common with type 'Params'. + + +==== excessPropertyCheckSpreadFunctionParam.ts (4 errors) ==== + type Params = { + a?: any; + b?: any; + } + + function f(params: Params) { + return; + } + + const objWithAllowedKeys = { a: 2 } + const objWithForbiddenKeys = { c: 2 } + const objWithNoKeys = {} + const a = 2; + const c = 2; + + f({ ...objWithAllowedKeys }) + f({ ...objWithForbiddenKeys }) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2559: Type '{ c: number; }' has no properties in common with type 'Params'. + f({ ...objWithAllowedKeys, ...objWithForbiddenKeys }) + + f({ ...{ a: 2 }, ...{ c: 2 } }) + f({ ...{ a: 2, c: 2 } }) + f({ ...{ c: 2 }, ...{ b: 2 } }) + + f({ ...{ a: 2 }, ...objWithForbiddenKeys }) + + f({ ...{ c: 2 }, ...objWithAllowedKeys }) + f({ ...{ c: 2 }, ...objWithForbiddenKeys }) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2559: Type '{ c: number; }' has no properties in common with type 'Params'. + f({ ...{ c: 2 }, ...objWithNoKeys }) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2559: Type '{ c: number; }' has no properties in common with type 'Params'. + + f({ ...{...{ c: 2 }, ...objWithNoKeys } }) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2559: Type '{ c: number; }' has no properties in common with type 'Params'. + + f({ a, ...{ c: 2 } }) + f({ a, ...{ c } }) + f({ ...{ c }, ...objWithAllowedKeys }) + + + + + \ No newline at end of file diff --git a/tests/baselines/reference/excessPropertyCheckSpreadFunctionParam.symbols b/tests/baselines/reference/excessPropertyCheckSpreadFunctionParam.symbols new file mode 100644 index 0000000000000..36d493972cb47 --- /dev/null +++ b/tests/baselines/reference/excessPropertyCheckSpreadFunctionParam.symbols @@ -0,0 +1,110 @@ +//// [tests/cases/compiler/excessPropertyCheckSpreadFunctionParam.ts] //// + +=== excessPropertyCheckSpreadFunctionParam.ts === +type Params = { +>Params : Symbol(Params, Decl(excessPropertyCheckSpreadFunctionParam.ts, 0, 0)) + + a?: any; +>a : Symbol(a, Decl(excessPropertyCheckSpreadFunctionParam.ts, 0, 15)) + + b?: any; +>b : Symbol(b, Decl(excessPropertyCheckSpreadFunctionParam.ts, 1, 12)) +} + +function f(params: Params) { +>f : Symbol(f, Decl(excessPropertyCheckSpreadFunctionParam.ts, 3, 1)) +>params : Symbol(params, Decl(excessPropertyCheckSpreadFunctionParam.ts, 5, 11)) +>Params : Symbol(Params, Decl(excessPropertyCheckSpreadFunctionParam.ts, 0, 0)) + + return; +} + +const objWithAllowedKeys = { a: 2 } +>objWithAllowedKeys : Symbol(objWithAllowedKeys, Decl(excessPropertyCheckSpreadFunctionParam.ts, 9, 5)) +>a : Symbol(a, Decl(excessPropertyCheckSpreadFunctionParam.ts, 9, 28)) + +const objWithForbiddenKeys = { c: 2 } +>objWithForbiddenKeys : Symbol(objWithForbiddenKeys, Decl(excessPropertyCheckSpreadFunctionParam.ts, 10, 5)) +>c : Symbol(c, Decl(excessPropertyCheckSpreadFunctionParam.ts, 10, 30)) + +const objWithNoKeys = {} +>objWithNoKeys : Symbol(objWithNoKeys, Decl(excessPropertyCheckSpreadFunctionParam.ts, 11, 5)) + +const a = 2; +>a : Symbol(a, Decl(excessPropertyCheckSpreadFunctionParam.ts, 12, 5)) + +const c = 2; +>c : Symbol(c, Decl(excessPropertyCheckSpreadFunctionParam.ts, 13, 5)) + +f({ ...objWithAllowedKeys }) +>f : Symbol(f, Decl(excessPropertyCheckSpreadFunctionParam.ts, 3, 1)) +>objWithAllowedKeys : Symbol(objWithAllowedKeys, Decl(excessPropertyCheckSpreadFunctionParam.ts, 9, 5)) + +f({ ...objWithForbiddenKeys }) +>f : Symbol(f, Decl(excessPropertyCheckSpreadFunctionParam.ts, 3, 1)) +>objWithForbiddenKeys : Symbol(objWithForbiddenKeys, Decl(excessPropertyCheckSpreadFunctionParam.ts, 10, 5)) + +f({ ...objWithAllowedKeys, ...objWithForbiddenKeys }) +>f : Symbol(f, Decl(excessPropertyCheckSpreadFunctionParam.ts, 3, 1)) +>objWithAllowedKeys : Symbol(objWithAllowedKeys, Decl(excessPropertyCheckSpreadFunctionParam.ts, 9, 5)) +>objWithForbiddenKeys : Symbol(objWithForbiddenKeys, Decl(excessPropertyCheckSpreadFunctionParam.ts, 10, 5)) + +f({ ...{ a: 2 }, ...{ c: 2 } }) +>f : Symbol(f, Decl(excessPropertyCheckSpreadFunctionParam.ts, 3, 1)) +>a : Symbol(a, Decl(excessPropertyCheckSpreadFunctionParam.ts, 19, 8)) +>c : Symbol(c, Decl(excessPropertyCheckSpreadFunctionParam.ts, 19, 21)) + +f({ ...{ a: 2, c: 2 } }) +>f : Symbol(f, Decl(excessPropertyCheckSpreadFunctionParam.ts, 3, 1)) +>a : Symbol(a, Decl(excessPropertyCheckSpreadFunctionParam.ts, 20, 8)) +>c : Symbol(c, Decl(excessPropertyCheckSpreadFunctionParam.ts, 20, 14)) + +f({ ...{ c: 2 }, ...{ b: 2 } }) +>f : Symbol(f, Decl(excessPropertyCheckSpreadFunctionParam.ts, 3, 1)) +>c : Symbol(c, Decl(excessPropertyCheckSpreadFunctionParam.ts, 21, 8)) +>b : Symbol(b, Decl(excessPropertyCheckSpreadFunctionParam.ts, 21, 21)) + +f({ ...{ a: 2 }, ...objWithForbiddenKeys }) +>f : Symbol(f, Decl(excessPropertyCheckSpreadFunctionParam.ts, 3, 1)) +>a : Symbol(a, Decl(excessPropertyCheckSpreadFunctionParam.ts, 23, 8)) +>objWithForbiddenKeys : Symbol(objWithForbiddenKeys, Decl(excessPropertyCheckSpreadFunctionParam.ts, 10, 5)) + +f({ ...{ c: 2 }, ...objWithAllowedKeys }) +>f : Symbol(f, Decl(excessPropertyCheckSpreadFunctionParam.ts, 3, 1)) +>c : Symbol(c, Decl(excessPropertyCheckSpreadFunctionParam.ts, 25, 8)) +>objWithAllowedKeys : Symbol(objWithAllowedKeys, Decl(excessPropertyCheckSpreadFunctionParam.ts, 9, 5)) + +f({ ...{ c: 2 }, ...objWithForbiddenKeys }) +>f : Symbol(f, Decl(excessPropertyCheckSpreadFunctionParam.ts, 3, 1)) +>c : Symbol(c, Decl(excessPropertyCheckSpreadFunctionParam.ts, 26, 8)) +>objWithForbiddenKeys : Symbol(objWithForbiddenKeys, Decl(excessPropertyCheckSpreadFunctionParam.ts, 10, 5)) + +f({ ...{ c: 2 }, ...objWithNoKeys }) +>f : Symbol(f, Decl(excessPropertyCheckSpreadFunctionParam.ts, 3, 1)) +>c : Symbol(c, Decl(excessPropertyCheckSpreadFunctionParam.ts, 27, 8)) +>objWithNoKeys : Symbol(objWithNoKeys, Decl(excessPropertyCheckSpreadFunctionParam.ts, 11, 5)) + +f({ ...{...{ c: 2 }, ...objWithNoKeys } }) +>f : Symbol(f, Decl(excessPropertyCheckSpreadFunctionParam.ts, 3, 1)) +>c : Symbol(c, Decl(excessPropertyCheckSpreadFunctionParam.ts, 29, 12)) +>objWithNoKeys : Symbol(objWithNoKeys, Decl(excessPropertyCheckSpreadFunctionParam.ts, 11, 5)) + +f({ a, ...{ c: 2 } }) +>f : Symbol(f, Decl(excessPropertyCheckSpreadFunctionParam.ts, 3, 1)) +>a : Symbol(a, Decl(excessPropertyCheckSpreadFunctionParam.ts, 31, 3)) +>c : Symbol(c, Decl(excessPropertyCheckSpreadFunctionParam.ts, 31, 11)) + +f({ a, ...{ c } }) +>f : Symbol(f, Decl(excessPropertyCheckSpreadFunctionParam.ts, 3, 1)) +>a : Symbol(a, Decl(excessPropertyCheckSpreadFunctionParam.ts, 32, 3)) +>c : Symbol(c, Decl(excessPropertyCheckSpreadFunctionParam.ts, 32, 11)) + +f({ ...{ c }, ...objWithAllowedKeys }) +>f : Symbol(f, Decl(excessPropertyCheckSpreadFunctionParam.ts, 3, 1)) +>c : Symbol(c, Decl(excessPropertyCheckSpreadFunctionParam.ts, 33, 8)) +>objWithAllowedKeys : Symbol(objWithAllowedKeys, Decl(excessPropertyCheckSpreadFunctionParam.ts, 9, 5)) + + + + + diff --git a/tests/baselines/reference/excessPropertyCheckSpreadFunctionParam.types b/tests/baselines/reference/excessPropertyCheckSpreadFunctionParam.types new file mode 100644 index 0000000000000..8d04130e75f52 --- /dev/null +++ b/tests/baselines/reference/excessPropertyCheckSpreadFunctionParam.types @@ -0,0 +1,283 @@ +//// [tests/cases/compiler/excessPropertyCheckSpreadFunctionParam.ts] //// + +=== excessPropertyCheckSpreadFunctionParam.ts === +type Params = { +>Params : Params +> : ^^^^^^ + + a?: any; +>a : any +> : ^^^ + + b?: any; +>b : any +> : ^^^ +} + +function f(params: Params) { +>f : (params: Params) => void +> : ^ ^^ ^^^^^^^^^ +>params : Params +> : ^^^^^^ + + return; +} + +const objWithAllowedKeys = { a: 2 } +>objWithAllowedKeys : { a: number; } +> : ^^^^^^^^^^^^^^ +>{ a: 2 } : { a: number; } +> : ^^^^^^^^^^^^^^ +>a : number +> : ^^^^^^ +>2 : 2 +> : ^ + +const objWithForbiddenKeys = { c: 2 } +>objWithForbiddenKeys : { c: number; } +> : ^^^^^^^^^^^^^^ +>{ c: 2 } : { c: number; } +> : ^^^^^^^^^^^^^^ +>c : number +> : ^^^^^^ +>2 : 2 +> : ^ + +const objWithNoKeys = {} +>objWithNoKeys : {} +> : ^^ +>{} : {} +> : ^^ + +const a = 2; +>a : 2 +> : ^ +>2 : 2 +> : ^ + +const c = 2; +>c : 2 +> : ^ +>2 : 2 +> : ^ + +f({ ...objWithAllowedKeys }) +>f({ ...objWithAllowedKeys }) : void +> : ^^^^ +>f : (params: Params) => void +> : ^ ^^ ^^^^^^^^^ +>{ ...objWithAllowedKeys } : { a: number; } +> : ^^^^^^^^^^^^^^ +>objWithAllowedKeys : { a: number; } +> : ^^^^^^^^^^^^^^ + +f({ ...objWithForbiddenKeys }) +>f({ ...objWithForbiddenKeys }) : void +> : ^^^^ +>f : (params: Params) => void +> : ^ ^^ ^^^^^^^^^ +>{ ...objWithForbiddenKeys } : { c: number; } +> : ^^^^^^^^^^^^^^ +>objWithForbiddenKeys : { c: number; } +> : ^^^^^^^^^^^^^^ + +f({ ...objWithAllowedKeys, ...objWithForbiddenKeys }) +>f({ ...objWithAllowedKeys, ...objWithForbiddenKeys }) : void +> : ^^^^ +>f : (params: Params) => void +> : ^ ^^ ^^^^^^^^^ +>{ ...objWithAllowedKeys, ...objWithForbiddenKeys } : { c: number; a: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ +>objWithAllowedKeys : { a: number; } +> : ^^^^^^^^^^^^^^ +>objWithForbiddenKeys : { c: number; } +> : ^^^^^^^^^^^^^^ + +f({ ...{ a: 2 }, ...{ c: 2 } }) +>f({ ...{ a: 2 }, ...{ c: 2 } }) : void +> : ^^^^ +>f : (params: Params) => void +> : ^ ^^ ^^^^^^^^^ +>{ ...{ a: 2 }, ...{ c: 2 } } : { c: number; a: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ a: 2 } : { a: number; } +> : ^^^^^^^^^^^^^^ +>a : number +> : ^^^^^^ +>2 : 2 +> : ^ +>{ c: 2 } : { c: number; } +> : ^^^^^^^^^^^^^^ +>c : number +> : ^^^^^^ +>2 : 2 +> : ^ + +f({ ...{ a: 2, c: 2 } }) +>f({ ...{ a: 2, c: 2 } }) : void +> : ^^^^ +>f : (params: Params) => void +> : ^ ^^ ^^^^^^^^^ +>{ ...{ a: 2, c: 2 } } : { a: number; c: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ a: 2, c: 2 } : { a: number; c: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ +>a : number +> : ^^^^^^ +>2 : 2 +> : ^ +>c : number +> : ^^^^^^ +>2 : 2 +> : ^ + +f({ ...{ c: 2 }, ...{ b: 2 } }) +>f({ ...{ c: 2 }, ...{ b: 2 } }) : void +> : ^^^^ +>f : (params: Params) => void +> : ^ ^^ ^^^^^^^^^ +>{ ...{ c: 2 }, ...{ b: 2 } } : { b: number; c: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ c: 2 } : { c: number; } +> : ^^^^^^^^^^^^^^ +>c : number +> : ^^^^^^ +>2 : 2 +> : ^ +>{ b: 2 } : { b: number; } +> : ^^^^^^^^^^^^^^ +>b : number +> : ^^^^^^ +>2 : 2 +> : ^ + +f({ ...{ a: 2 }, ...objWithForbiddenKeys }) +>f({ ...{ a: 2 }, ...objWithForbiddenKeys }) : void +> : ^^^^ +>f : (params: Params) => void +> : ^ ^^ ^^^^^^^^^ +>{ ...{ a: 2 }, ...objWithForbiddenKeys } : { c: number; a: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ a: 2 } : { a: number; } +> : ^^^^^^^^^^^^^^ +>a : number +> : ^^^^^^ +>2 : 2 +> : ^ +>objWithForbiddenKeys : { c: number; } +> : ^^^^^^^^^^^^^^ + +f({ ...{ c: 2 }, ...objWithAllowedKeys }) +>f({ ...{ c: 2 }, ...objWithAllowedKeys }) : void +> : ^^^^ +>f : (params: Params) => void +> : ^ ^^ ^^^^^^^^^ +>{ ...{ c: 2 }, ...objWithAllowedKeys } : { a: number; c: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ c: 2 } : { c: number; } +> : ^^^^^^^^^^^^^^ +>c : number +> : ^^^^^^ +>2 : 2 +> : ^ +>objWithAllowedKeys : { a: number; } +> : ^^^^^^^^^^^^^^ + +f({ ...{ c: 2 }, ...objWithForbiddenKeys }) +>f({ ...{ c: 2 }, ...objWithForbiddenKeys }) : void +> : ^^^^ +>f : (params: Params) => void +> : ^ ^^ ^^^^^^^^^ +>{ ...{ c: 2 }, ...objWithForbiddenKeys } : { c: number; } +> : ^^^^^^^^^^^^^^ +>{ c: 2 } : { c: number; } +> : ^^^^^^^^^^^^^^ +>c : number +> : ^^^^^^ +>2 : 2 +> : ^ +>objWithForbiddenKeys : { c: number; } +> : ^^^^^^^^^^^^^^ + +f({ ...{ c: 2 }, ...objWithNoKeys }) +>f({ ...{ c: 2 }, ...objWithNoKeys }) : void +> : ^^^^ +>f : (params: Params) => void +> : ^ ^^ ^^^^^^^^^ +>{ ...{ c: 2 }, ...objWithNoKeys } : { c: number; } +> : ^^^^^^^^^^^^^^ +>{ c: 2 } : { c: number; } +> : ^^^^^^^^^^^^^^ +>c : number +> : ^^^^^^ +>2 : 2 +> : ^ +>objWithNoKeys : {} +> : ^^ + +f({ ...{...{ c: 2 }, ...objWithNoKeys } }) +>f({ ...{...{ c: 2 }, ...objWithNoKeys } }) : void +> : ^^^^ +>f : (params: Params) => void +> : ^ ^^ ^^^^^^^^^ +>{ ...{...{ c: 2 }, ...objWithNoKeys } } : { c: number; } +> : ^^^^^^^^^^^^^^ +>{...{ c: 2 }, ...objWithNoKeys } : { c: number; } +> : ^^^^^^^^^^^^^^ +>{ c: 2 } : { c: number; } +> : ^^^^^^^^^^^^^^ +>c : number +> : ^^^^^^ +>2 : 2 +> : ^ +>objWithNoKeys : {} +> : ^^ + +f({ a, ...{ c: 2 } }) +>f({ a, ...{ c: 2 } }) : void +> : ^^^^ +>f : (params: Params) => void +> : ^ ^^ ^^^^^^^^^ +>{ a, ...{ c: 2 } } : { c: number; a: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ +>a : number +> : ^^^^^^ +>{ c: 2 } : { c: number; } +> : ^^^^^^^^^^^^^^ +>c : number +> : ^^^^^^ +>2 : 2 +> : ^ + +f({ a, ...{ c } }) +>f({ a, ...{ c } }) : void +> : ^^^^ +>f : (params: Params) => void +> : ^ ^^ ^^^^^^^^^ +>{ a, ...{ c } } : { c: number; a: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ +>a : number +> : ^^^^^^ +>{ c } : { c: number; } +> : ^^^^^^^^^^^^^^ +>c : number +> : ^^^^^^ + +f({ ...{ c }, ...objWithAllowedKeys }) +>f({ ...{ c }, ...objWithAllowedKeys }) : void +> : ^^^^ +>f : (params: Params) => void +> : ^ ^^ ^^^^^^^^^ +>{ ...{ c }, ...objWithAllowedKeys } : { a: number; c: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ c } : { c: number; } +> : ^^^^^^^^^^^^^^ +>c : number +> : ^^^^^^ +>objWithAllowedKeys : { a: number; } +> : ^^^^^^^^^^^^^^ + + + + + diff --git a/tests/baselines/reference/excessPropertyCheckSpreadInlineObject.errors.txt b/tests/baselines/reference/excessPropertyCheckSpreadInlineObject.errors.txt new file mode 100644 index 0000000000000..af0622d306b84 --- /dev/null +++ b/tests/baselines/reference/excessPropertyCheckSpreadInlineObject.errors.txt @@ -0,0 +1,26 @@ +excessPropertyCheckSpreadInlineObject.ts(7,9): error TS2353: Object literal may only specify known properties, and 'excessProperty' does not exist in type 'MyObject'. +excessPropertyCheckSpreadInlineObject.ts(15,9): error TS2353: Object literal may only specify known properties, and 'excessProperty' does not exist in type 'MyObject'. + + +==== excessPropertyCheckSpreadInlineObject.ts (2 errors) ==== + type MyObject = { foo: number; bar?: number }; + + const b: MyObject = { + foo: 1, + ...{ + bar: 2, + excessProperty: 3, + ~~~~~~~~~~~~~~ +!!! error TS2353: Object literal may only specify known properties, and 'excessProperty' does not exist in type 'MyObject'. + }, + }; + + const b2 = { + foo: 1, + ...{ + bar: 2, + excessProperty: 3, + ~~~~~~~~~~~~~~ +!!! error TS2353: Object literal may only specify known properties, and 'excessProperty' does not exist in type 'MyObject'. + }, + } satisfies MyObject; \ No newline at end of file diff --git a/tests/baselines/reference/excessPropertyCheckSpreadInlineObject.symbols b/tests/baselines/reference/excessPropertyCheckSpreadInlineObject.symbols new file mode 100644 index 0000000000000..549e21f7af29c --- /dev/null +++ b/tests/baselines/reference/excessPropertyCheckSpreadInlineObject.symbols @@ -0,0 +1,42 @@ +//// [tests/cases/compiler/excessPropertyCheckSpreadInlineObject.ts] //// + +=== excessPropertyCheckSpreadInlineObject.ts === +type MyObject = { foo: number; bar?: number }; +>MyObject : Symbol(MyObject, Decl(excessPropertyCheckSpreadInlineObject.ts, 0, 0)) +>foo : Symbol(foo, Decl(excessPropertyCheckSpreadInlineObject.ts, 0, 17)) +>bar : Symbol(bar, Decl(excessPropertyCheckSpreadInlineObject.ts, 0, 30)) + +const b: MyObject = { +>b : Symbol(b, Decl(excessPropertyCheckSpreadInlineObject.ts, 2, 5)) +>MyObject : Symbol(MyObject, Decl(excessPropertyCheckSpreadInlineObject.ts, 0, 0)) + + foo: 1, +>foo : Symbol(foo, Decl(excessPropertyCheckSpreadInlineObject.ts, 2, 21)) + + ...{ + bar: 2, +>bar : Symbol(bar, Decl(excessPropertyCheckSpreadInlineObject.ts, 4, 8)) + + excessProperty: 3, +>excessProperty : Symbol(excessProperty, Decl(excessPropertyCheckSpreadInlineObject.ts, 5, 15)) + + }, +}; + +const b2 = { +>b2 : Symbol(b2, Decl(excessPropertyCheckSpreadInlineObject.ts, 10, 5)) + + foo: 1, +>foo : Symbol(foo, Decl(excessPropertyCheckSpreadInlineObject.ts, 10, 12)) + + ...{ + bar: 2, +>bar : Symbol(bar, Decl(excessPropertyCheckSpreadInlineObject.ts, 12, 8)) + + excessProperty: 3, +>excessProperty : Symbol(excessProperty, Decl(excessPropertyCheckSpreadInlineObject.ts, 13, 15)) + + }, +} satisfies MyObject; +>MyObject : Symbol(MyObject, Decl(excessPropertyCheckSpreadInlineObject.ts, 0, 0)) + diff --git a/tests/baselines/reference/excessPropertyCheckSpreadInlineObject.types b/tests/baselines/reference/excessPropertyCheckSpreadInlineObject.types new file mode 100644 index 0000000000000..ac20311c174c2 --- /dev/null +++ b/tests/baselines/reference/excessPropertyCheckSpreadInlineObject.types @@ -0,0 +1,74 @@ +//// [tests/cases/compiler/excessPropertyCheckSpreadInlineObject.ts] //// + +=== excessPropertyCheckSpreadInlineObject.ts === +type MyObject = { foo: number; bar?: number }; +>MyObject : MyObject +> : ^^^^^^^^ +>foo : number +> : ^^^^^^ +>bar : number | undefined +> : ^^^^^^^^^^^^^^^^^^ + +const b: MyObject = { +>b : MyObject +> : ^^^^^^^^ +>{ foo: 1, ...{ bar: 2, excessProperty: 3, },} : { bar: number; excessProperty: number; foo: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + foo: 1, +>foo : number +> : ^^^^^^ +>1 : 1 +> : ^ + + ...{ +>{ bar: 2, excessProperty: 3, } : { bar: number; excessProperty: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + bar: 2, +>bar : number +> : ^^^^^^ +>2 : 2 +> : ^ + + excessProperty: 3, +>excessProperty : number +> : ^^^^^^ +>3 : 3 +> : ^ + + }, +}; + +const b2 = { +>b2 : { bar: number; excessProperty: number; foo: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ foo: 1, ...{ bar: 2, excessProperty: 3, },} satisfies MyObject : { bar: number; excessProperty: number; foo: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ foo: 1, ...{ bar: 2, excessProperty: 3, },} : { bar: number; excessProperty: number; foo: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + foo: 1, +>foo : number +> : ^^^^^^ +>1 : 1 +> : ^ + + ...{ +>{ bar: 2, excessProperty: 3, } : { bar: number; excessProperty: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + bar: 2, +>bar : number +> : ^^^^^^ +>2 : 2 +> : ^ + + excessProperty: 3, +>excessProperty : number +> : ^^^^^^ +>3 : 3 +> : ^ + + }, +} satisfies MyObject; diff --git a/tests/baselines/reference/excessPropertyCheckSpreadReturn.errors.txt b/tests/baselines/reference/excessPropertyCheckSpreadReturn.errors.txt new file mode 100644 index 0000000000000..8fd4de333db12 --- /dev/null +++ b/tests/baselines/reference/excessPropertyCheckSpreadReturn.errors.txt @@ -0,0 +1,102 @@ +excessPropertyCheckSpreadReturn.ts(16,5): error TS2559: Type '{ c: number; }' has no properties in common with type 'FReturnType'. +excessPropertyCheckSpreadReturn.ts(24,32): error TS2353: Object literal may only specify known properties, and 'c' does not exist in type 'FReturnType'. +excessPropertyCheckSpreadReturn.ts(28,25): error TS2353: Object literal may only specify known properties, and 'c' does not exist in type 'FReturnType'. +excessPropertyCheckSpreadReturn.ts(32,19): error TS2353: Object literal may only specify known properties, and 'c' does not exist in type 'FReturnType'. +excessPropertyCheckSpreadReturn.ts(40,19): error TS2353: Object literal may only specify known properties, and 'c' does not exist in type 'FReturnType'. +excessPropertyCheckSpreadReturn.ts(44,5): error TS2559: Type '{ c: number; }' has no properties in common with type 'FReturnType'. +excessPropertyCheckSpreadReturn.ts(48,19): error TS2353: Object literal may only specify known properties, and 'c' does not exist in type 'FReturnType'. +excessPropertyCheckSpreadReturn.ts(52,23): error TS2353: Object literal may only specify known properties, and 'c' does not exist in type 'FReturnType'. +excessPropertyCheckSpreadReturn.ts(56,22): error TS2353: Object literal may only specify known properties, and 'c' does not exist in type 'FReturnType'. +excessPropertyCheckSpreadReturn.ts(60,22): error TS2353: Object literal may only specify known properties, and 'c' does not exist in type 'FReturnType'. +excessPropertyCheckSpreadReturn.ts(64,19): error TS2353: Object literal may only specify known properties, and 'c' does not exist in type 'FReturnType'. + + +==== excessPropertyCheckSpreadReturn.ts (11 errors) ==== + type FReturnType = { + a?: any; + b?: any; + } + const objWithAllowedKeys = { a: 2 } + const objWithForbiddenKeys = { c: 2 } + const objWithNoKeys = {} + const a = 2; + const c = 2; + + function f1(): FReturnType { + return { ...objWithAllowedKeys }; + } + + function f2(): FReturnType { + return { ...objWithForbiddenKeys }; + ~~~~~~ +!!! error TS2559: Type '{ c: number; }' has no properties in common with type 'FReturnType'. + } + + function f3(): FReturnType { + return { ...objWithAllowedKeys, ...objWithForbiddenKeys }; + } + + function f4(): FReturnType { + return { ...{ a: 2 }, ...{ c: 2 } }; + ~ +!!! error TS2353: Object literal may only specify known properties, and 'c' does not exist in type 'FReturnType'. + } + + function f5(): FReturnType { + return { ...{ a: 2, c: 2 } }; + ~ +!!! error TS2353: Object literal may only specify known properties, and 'c' does not exist in type 'FReturnType'. + } + + function f6(): FReturnType { + return { ...{ c: 2 }, ...{ b: 2 } }; + ~ +!!! error TS2353: Object literal may only specify known properties, and 'c' does not exist in type 'FReturnType'. + } + + function f7(): FReturnType { + return { ...{ a: 2 }, ...objWithForbiddenKeys }; + } + + function f8(): FReturnType { + return { ...{ c: 2 }, ...objWithAllowedKeys }; + ~ +!!! error TS2353: Object literal may only specify known properties, and 'c' does not exist in type 'FReturnType'. + } + + function f9(): FReturnType { + return { ...{ c: 2 }, ...objWithForbiddenKeys }; + ~~~~~~ +!!! error TS2559: Type '{ c: number; }' has no properties in common with type 'FReturnType'. + } + + function f10(): FReturnType { + return { ...{ c: 2 }, ...objWithNoKeys }; + ~ +!!! error TS2353: Object literal may only specify known properties, and 'c' does not exist in type 'FReturnType'. + } + + function f11(): FReturnType { + return { ...{...{ c: 2 }, ...objWithNoKeys } }; + ~ +!!! error TS2353: Object literal may only specify known properties, and 'c' does not exist in type 'FReturnType'. + } + + function f12(): FReturnType { + return { a, ...{ c: 2 } }; + ~ +!!! error TS2353: Object literal may only specify known properties, and 'c' does not exist in type 'FReturnType'. + } + + function f13(): FReturnType { + return { a, ...{ c } }; + ~ +!!! error TS2353: Object literal may only specify known properties, and 'c' does not exist in type 'FReturnType'. + } + + function f14(): FReturnType { + return { ...{ c }, ...objWithAllowedKeys }; + ~ +!!! error TS2353: Object literal may only specify known properties, and 'c' does not exist in type 'FReturnType'. + } + \ No newline at end of file diff --git a/tests/baselines/reference/excessPropertyCheckSpreadReturn.symbols b/tests/baselines/reference/excessPropertyCheckSpreadReturn.symbols new file mode 100644 index 0000000000000..eebf4f20fedcc --- /dev/null +++ b/tests/baselines/reference/excessPropertyCheckSpreadReturn.symbols @@ -0,0 +1,153 @@ +//// [tests/cases/compiler/excessPropertyCheckSpreadReturn.ts] //// + +=== excessPropertyCheckSpreadReturn.ts === +type FReturnType = { +>FReturnType : Symbol(FReturnType, Decl(excessPropertyCheckSpreadReturn.ts, 0, 0)) + + a?: any; +>a : Symbol(a, Decl(excessPropertyCheckSpreadReturn.ts, 0, 20)) + + b?: any; +>b : Symbol(b, Decl(excessPropertyCheckSpreadReturn.ts, 1, 12)) +} +const objWithAllowedKeys = { a: 2 } +>objWithAllowedKeys : Symbol(objWithAllowedKeys, Decl(excessPropertyCheckSpreadReturn.ts, 4, 5)) +>a : Symbol(a, Decl(excessPropertyCheckSpreadReturn.ts, 4, 28)) + +const objWithForbiddenKeys = { c: 2 } +>objWithForbiddenKeys : Symbol(objWithForbiddenKeys, Decl(excessPropertyCheckSpreadReturn.ts, 5, 5)) +>c : Symbol(c, Decl(excessPropertyCheckSpreadReturn.ts, 5, 30)) + +const objWithNoKeys = {} +>objWithNoKeys : Symbol(objWithNoKeys, Decl(excessPropertyCheckSpreadReturn.ts, 6, 5)) + +const a = 2; +>a : Symbol(a, Decl(excessPropertyCheckSpreadReturn.ts, 7, 5)) + +const c = 2; +>c : Symbol(c, Decl(excessPropertyCheckSpreadReturn.ts, 8, 5)) + +function f1(): FReturnType { +>f1 : Symbol(f1, Decl(excessPropertyCheckSpreadReturn.ts, 8, 12)) +>FReturnType : Symbol(FReturnType, Decl(excessPropertyCheckSpreadReturn.ts, 0, 0)) + + return { ...objWithAllowedKeys }; +>objWithAllowedKeys : Symbol(objWithAllowedKeys, Decl(excessPropertyCheckSpreadReturn.ts, 4, 5)) +} + +function f2(): FReturnType { +>f2 : Symbol(f2, Decl(excessPropertyCheckSpreadReturn.ts, 12, 1)) +>FReturnType : Symbol(FReturnType, Decl(excessPropertyCheckSpreadReturn.ts, 0, 0)) + + return { ...objWithForbiddenKeys }; +>objWithForbiddenKeys : Symbol(objWithForbiddenKeys, Decl(excessPropertyCheckSpreadReturn.ts, 5, 5)) +} + +function f3(): FReturnType { +>f3 : Symbol(f3, Decl(excessPropertyCheckSpreadReturn.ts, 16, 1)) +>FReturnType : Symbol(FReturnType, Decl(excessPropertyCheckSpreadReturn.ts, 0, 0)) + + return { ...objWithAllowedKeys, ...objWithForbiddenKeys }; +>objWithAllowedKeys : Symbol(objWithAllowedKeys, Decl(excessPropertyCheckSpreadReturn.ts, 4, 5)) +>objWithForbiddenKeys : Symbol(objWithForbiddenKeys, Decl(excessPropertyCheckSpreadReturn.ts, 5, 5)) +} + +function f4(): FReturnType { +>f4 : Symbol(f4, Decl(excessPropertyCheckSpreadReturn.ts, 20, 1)) +>FReturnType : Symbol(FReturnType, Decl(excessPropertyCheckSpreadReturn.ts, 0, 0)) + + return { ...{ a: 2 }, ...{ c: 2 } }; +>a : Symbol(a, Decl(excessPropertyCheckSpreadReturn.ts, 23, 17)) +>c : Symbol(c, Decl(excessPropertyCheckSpreadReturn.ts, 23, 30)) +} + +function f5(): FReturnType { +>f5 : Symbol(f5, Decl(excessPropertyCheckSpreadReturn.ts, 24, 1)) +>FReturnType : Symbol(FReturnType, Decl(excessPropertyCheckSpreadReturn.ts, 0, 0)) + + return { ...{ a: 2, c: 2 } }; +>a : Symbol(a, Decl(excessPropertyCheckSpreadReturn.ts, 27, 17)) +>c : Symbol(c, Decl(excessPropertyCheckSpreadReturn.ts, 27, 23)) +} + +function f6(): FReturnType { +>f6 : Symbol(f6, Decl(excessPropertyCheckSpreadReturn.ts, 28, 1)) +>FReturnType : Symbol(FReturnType, Decl(excessPropertyCheckSpreadReturn.ts, 0, 0)) + + return { ...{ c: 2 }, ...{ b: 2 } }; +>c : Symbol(c, Decl(excessPropertyCheckSpreadReturn.ts, 31, 17)) +>b : Symbol(b, Decl(excessPropertyCheckSpreadReturn.ts, 31, 30)) +} + +function f7(): FReturnType { +>f7 : Symbol(f7, Decl(excessPropertyCheckSpreadReturn.ts, 32, 1)) +>FReturnType : Symbol(FReturnType, Decl(excessPropertyCheckSpreadReturn.ts, 0, 0)) + + return { ...{ a: 2 }, ...objWithForbiddenKeys }; +>a : Symbol(a, Decl(excessPropertyCheckSpreadReturn.ts, 35, 17)) +>objWithForbiddenKeys : Symbol(objWithForbiddenKeys, Decl(excessPropertyCheckSpreadReturn.ts, 5, 5)) +} + +function f8(): FReturnType { +>f8 : Symbol(f8, Decl(excessPropertyCheckSpreadReturn.ts, 36, 1)) +>FReturnType : Symbol(FReturnType, Decl(excessPropertyCheckSpreadReturn.ts, 0, 0)) + + return { ...{ c: 2 }, ...objWithAllowedKeys }; +>c : Symbol(c, Decl(excessPropertyCheckSpreadReturn.ts, 39, 17)) +>objWithAllowedKeys : Symbol(objWithAllowedKeys, Decl(excessPropertyCheckSpreadReturn.ts, 4, 5)) +} + +function f9(): FReturnType { +>f9 : Symbol(f9, Decl(excessPropertyCheckSpreadReturn.ts, 40, 1)) +>FReturnType : Symbol(FReturnType, Decl(excessPropertyCheckSpreadReturn.ts, 0, 0)) + + return { ...{ c: 2 }, ...objWithForbiddenKeys }; +>c : Symbol(c, Decl(excessPropertyCheckSpreadReturn.ts, 43, 17)) +>objWithForbiddenKeys : Symbol(objWithForbiddenKeys, Decl(excessPropertyCheckSpreadReturn.ts, 5, 5)) +} + +function f10(): FReturnType { +>f10 : Symbol(f10, Decl(excessPropertyCheckSpreadReturn.ts, 44, 1)) +>FReturnType : Symbol(FReturnType, Decl(excessPropertyCheckSpreadReturn.ts, 0, 0)) + + return { ...{ c: 2 }, ...objWithNoKeys }; +>c : Symbol(c, Decl(excessPropertyCheckSpreadReturn.ts, 47, 17)) +>objWithNoKeys : Symbol(objWithNoKeys, Decl(excessPropertyCheckSpreadReturn.ts, 6, 5)) +} + +function f11(): FReturnType { +>f11 : Symbol(f11, Decl(excessPropertyCheckSpreadReturn.ts, 48, 1)) +>FReturnType : Symbol(FReturnType, Decl(excessPropertyCheckSpreadReturn.ts, 0, 0)) + + return { ...{...{ c: 2 }, ...objWithNoKeys } }; +>c : Symbol(c, Decl(excessPropertyCheckSpreadReturn.ts, 51, 21)) +>objWithNoKeys : Symbol(objWithNoKeys, Decl(excessPropertyCheckSpreadReturn.ts, 6, 5)) +} + +function f12(): FReturnType { +>f12 : Symbol(f12, Decl(excessPropertyCheckSpreadReturn.ts, 52, 1)) +>FReturnType : Symbol(FReturnType, Decl(excessPropertyCheckSpreadReturn.ts, 0, 0)) + + return { a, ...{ c: 2 } }; +>a : Symbol(a, Decl(excessPropertyCheckSpreadReturn.ts, 55, 12)) +>c : Symbol(c, Decl(excessPropertyCheckSpreadReturn.ts, 55, 20)) +} + +function f13(): FReturnType { +>f13 : Symbol(f13, Decl(excessPropertyCheckSpreadReturn.ts, 56, 1)) +>FReturnType : Symbol(FReturnType, Decl(excessPropertyCheckSpreadReturn.ts, 0, 0)) + + return { a, ...{ c } }; +>a : Symbol(a, Decl(excessPropertyCheckSpreadReturn.ts, 59, 12)) +>c : Symbol(c, Decl(excessPropertyCheckSpreadReturn.ts, 59, 20)) +} + +function f14(): FReturnType { +>f14 : Symbol(f14, Decl(excessPropertyCheckSpreadReturn.ts, 60, 1)) +>FReturnType : Symbol(FReturnType, Decl(excessPropertyCheckSpreadReturn.ts, 0, 0)) + + return { ...{ c }, ...objWithAllowedKeys }; +>c : Symbol(c, Decl(excessPropertyCheckSpreadReturn.ts, 63, 17)) +>objWithAllowedKeys : Symbol(objWithAllowedKeys, Decl(excessPropertyCheckSpreadReturn.ts, 4, 5)) +} + diff --git a/tests/baselines/reference/excessPropertyCheckSpreadReturn.types b/tests/baselines/reference/excessPropertyCheckSpreadReturn.types new file mode 100644 index 0000000000000..a868d91257968 --- /dev/null +++ b/tests/baselines/reference/excessPropertyCheckSpreadReturn.types @@ -0,0 +1,283 @@ +//// [tests/cases/compiler/excessPropertyCheckSpreadReturn.ts] //// + +=== excessPropertyCheckSpreadReturn.ts === +type FReturnType = { +>FReturnType : FReturnType +> : ^^^^^^^^^^^ + + a?: any; +>a : any +> : ^^^ + + b?: any; +>b : any +> : ^^^ +} +const objWithAllowedKeys = { a: 2 } +>objWithAllowedKeys : { a: number; } +> : ^^^^^^^^^^^^^^ +>{ a: 2 } : { a: number; } +> : ^^^^^^^^^^^^^^ +>a : number +> : ^^^^^^ +>2 : 2 +> : ^ + +const objWithForbiddenKeys = { c: 2 } +>objWithForbiddenKeys : { c: number; } +> : ^^^^^^^^^^^^^^ +>{ c: 2 } : { c: number; } +> : ^^^^^^^^^^^^^^ +>c : number +> : ^^^^^^ +>2 : 2 +> : ^ + +const objWithNoKeys = {} +>objWithNoKeys : {} +> : ^^ +>{} : {} +> : ^^ + +const a = 2; +>a : 2 +> : ^ +>2 : 2 +> : ^ + +const c = 2; +>c : 2 +> : ^ +>2 : 2 +> : ^ + +function f1(): FReturnType { +>f1 : () => FReturnType +> : ^^^^^^ + + return { ...objWithAllowedKeys }; +>{ ...objWithAllowedKeys } : { a: number; } +> : ^^^^^^^^^^^^^^ +>objWithAllowedKeys : { a: number; } +> : ^^^^^^^^^^^^^^ +} + +function f2(): FReturnType { +>f2 : () => FReturnType +> : ^^^^^^ + + return { ...objWithForbiddenKeys }; +>{ ...objWithForbiddenKeys } : { c: number; } +> : ^^^^^^^^^^^^^^ +>objWithForbiddenKeys : { c: number; } +> : ^^^^^^^^^^^^^^ +} + +function f3(): FReturnType { +>f3 : () => FReturnType +> : ^^^^^^ + + return { ...objWithAllowedKeys, ...objWithForbiddenKeys }; +>{ ...objWithAllowedKeys, ...objWithForbiddenKeys } : { c: number; a: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ +>objWithAllowedKeys : { a: number; } +> : ^^^^^^^^^^^^^^ +>objWithForbiddenKeys : { c: number; } +> : ^^^^^^^^^^^^^^ +} + +function f4(): FReturnType { +>f4 : () => FReturnType +> : ^^^^^^ + + return { ...{ a: 2 }, ...{ c: 2 } }; +>{ ...{ a: 2 }, ...{ c: 2 } } : { c: number; a: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ a: 2 } : { a: number; } +> : ^^^^^^^^^^^^^^ +>a : number +> : ^^^^^^ +>2 : 2 +> : ^ +>{ c: 2 } : { c: number; } +> : ^^^^^^^^^^^^^^ +>c : number +> : ^^^^^^ +>2 : 2 +> : ^ +} + +function f5(): FReturnType { +>f5 : () => FReturnType +> : ^^^^^^ + + return { ...{ a: 2, c: 2 } }; +>{ ...{ a: 2, c: 2 } } : { a: number; c: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ a: 2, c: 2 } : { a: number; c: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ +>a : number +> : ^^^^^^ +>2 : 2 +> : ^ +>c : number +> : ^^^^^^ +>2 : 2 +> : ^ +} + +function f6(): FReturnType { +>f6 : () => FReturnType +> : ^^^^^^ + + return { ...{ c: 2 }, ...{ b: 2 } }; +>{ ...{ c: 2 }, ...{ b: 2 } } : { b: number; c: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ c: 2 } : { c: number; } +> : ^^^^^^^^^^^^^^ +>c : number +> : ^^^^^^ +>2 : 2 +> : ^ +>{ b: 2 } : { b: number; } +> : ^^^^^^^^^^^^^^ +>b : number +> : ^^^^^^ +>2 : 2 +> : ^ +} + +function f7(): FReturnType { +>f7 : () => FReturnType +> : ^^^^^^ + + return { ...{ a: 2 }, ...objWithForbiddenKeys }; +>{ ...{ a: 2 }, ...objWithForbiddenKeys } : { c: number; a: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ a: 2 } : { a: number; } +> : ^^^^^^^^^^^^^^ +>a : number +> : ^^^^^^ +>2 : 2 +> : ^ +>objWithForbiddenKeys : { c: number; } +> : ^^^^^^^^^^^^^^ +} + +function f8(): FReturnType { +>f8 : () => FReturnType +> : ^^^^^^ + + return { ...{ c: 2 }, ...objWithAllowedKeys }; +>{ ...{ c: 2 }, ...objWithAllowedKeys } : { a: number; c: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ c: 2 } : { c: number; } +> : ^^^^^^^^^^^^^^ +>c : number +> : ^^^^^^ +>2 : 2 +> : ^ +>objWithAllowedKeys : { a: number; } +> : ^^^^^^^^^^^^^^ +} + +function f9(): FReturnType { +>f9 : () => FReturnType +> : ^^^^^^ + + return { ...{ c: 2 }, ...objWithForbiddenKeys }; +>{ ...{ c: 2 }, ...objWithForbiddenKeys } : { c: number; } +> : ^^^^^^^^^^^^^^ +>{ c: 2 } : { c: number; } +> : ^^^^^^^^^^^^^^ +>c : number +> : ^^^^^^ +>2 : 2 +> : ^ +>objWithForbiddenKeys : { c: number; } +> : ^^^^^^^^^^^^^^ +} + +function f10(): FReturnType { +>f10 : () => FReturnType +> : ^^^^^^ + + return { ...{ c: 2 }, ...objWithNoKeys }; +>{ ...{ c: 2 }, ...objWithNoKeys } : { c: number; } +> : ^^^^^^^^^^^^^^ +>{ c: 2 } : { c: number; } +> : ^^^^^^^^^^^^^^ +>c : number +> : ^^^^^^ +>2 : 2 +> : ^ +>objWithNoKeys : {} +> : ^^ +} + +function f11(): FReturnType { +>f11 : () => FReturnType +> : ^^^^^^ + + return { ...{...{ c: 2 }, ...objWithNoKeys } }; +>{ ...{...{ c: 2 }, ...objWithNoKeys } } : { c: number; } +> : ^^^^^^^^^^^^^^ +>{...{ c: 2 }, ...objWithNoKeys } : { c: number; } +> : ^^^^^^^^^^^^^^ +>{ c: 2 } : { c: number; } +> : ^^^^^^^^^^^^^^ +>c : number +> : ^^^^^^ +>2 : 2 +> : ^ +>objWithNoKeys : {} +> : ^^ +} + +function f12(): FReturnType { +>f12 : () => FReturnType +> : ^^^^^^ + + return { a, ...{ c: 2 } }; +>{ a, ...{ c: 2 } } : { c: number; a: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ +>a : number +> : ^^^^^^ +>{ c: 2 } : { c: number; } +> : ^^^^^^^^^^^^^^ +>c : number +> : ^^^^^^ +>2 : 2 +> : ^ +} + +function f13(): FReturnType { +>f13 : () => FReturnType +> : ^^^^^^ + + return { a, ...{ c } }; +>{ a, ...{ c } } : { c: number; a: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ +>a : number +> : ^^^^^^ +>{ c } : { c: number; } +> : ^^^^^^^^^^^^^^ +>c : number +> : ^^^^^^ +} + +function f14(): FReturnType { +>f14 : () => FReturnType +> : ^^^^^^ + + return { ...{ c }, ...objWithAllowedKeys }; +>{ ...{ c }, ...objWithAllowedKeys } : { a: number; c: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ c } : { c: number; } +> : ^^^^^^^^^^^^^^ +>c : number +> : ^^^^^^ +>objWithAllowedKeys : { a: number; } +> : ^^^^^^^^^^^^^^ +} + diff --git a/tests/baselines/reference/excessPropertyCheckSpreadSameExcessProperty.errors.txt b/tests/baselines/reference/excessPropertyCheckSpreadSameExcessProperty.errors.txt new file mode 100644 index 0000000000000..8e391f5d25cde --- /dev/null +++ b/tests/baselines/reference/excessPropertyCheckSpreadSameExcessProperty.errors.txt @@ -0,0 +1,35 @@ +excessPropertyCheckSpreadSameExcessProperty.ts(7,5): error TS2783: 'bar' is specified more than once, so this usage will be overwritten. +excessPropertyCheckSpreadSameExcessProperty.ts(9,18): error TS2353: Object literal may only specify known properties, and 'excessProperty' does not exist in type 'MyObj'. + + +==== excessPropertyCheckSpreadSameExcessProperty.ts (2 errors) ==== + type MyObj = { foo: number; bar: number }; + + const containsExcessProperty = { bar: 2, excessProperty: "A" }; + + const a1 : MyObj = { + foo: 1, + bar: 1, + ~~~~~~ +!!! error TS2783: 'bar' is specified more than once, so this usage will be overwritten. +!!! related TS2785 excessPropertyCheckSpreadSameExcessProperty.ts:8:5: This spread always overwrites this property. + ...containsExcessProperty, + ...{ bar: 2, excessProperty: "A" }, + ~~~~~~~~~~~~~~ +!!! error TS2353: Object literal may only specify known properties, and 'excessProperty' does not exist in type 'MyObj'. + }; + + // no EPC errors because the inline excessProperty will be overwritten + const a2 : MyObj = { + foo: 1, + ...{ bar: 2, excessProperty: "A" }, + ...containsExcessProperty, + bar: 1, + }; + + // no EPC errors because the inline excessProperty will be overwritten + const a3 : MyObj = { + foo: 1, + ...{ bar: 2, excessProperty: "A" }, + ...containsExcessProperty, + }; \ No newline at end of file diff --git a/tests/baselines/reference/excessPropertyCheckSpreadSameExcessProperty.symbols b/tests/baselines/reference/excessPropertyCheckSpreadSameExcessProperty.symbols new file mode 100644 index 0000000000000..936aedc76f477 --- /dev/null +++ b/tests/baselines/reference/excessPropertyCheckSpreadSameExcessProperty.symbols @@ -0,0 +1,68 @@ +//// [tests/cases/compiler/excessPropertyCheckSpreadSameExcessProperty.ts] //// + +=== excessPropertyCheckSpreadSameExcessProperty.ts === +type MyObj = { foo: number; bar: number }; +>MyObj : Symbol(MyObj, Decl(excessPropertyCheckSpreadSameExcessProperty.ts, 0, 0)) +>foo : Symbol(foo, Decl(excessPropertyCheckSpreadSameExcessProperty.ts, 0, 14)) +>bar : Symbol(bar, Decl(excessPropertyCheckSpreadSameExcessProperty.ts, 0, 27)) + +const containsExcessProperty = { bar: 2, excessProperty: "A" }; +>containsExcessProperty : Symbol(containsExcessProperty, Decl(excessPropertyCheckSpreadSameExcessProperty.ts, 2, 5)) +>bar : Symbol(bar, Decl(excessPropertyCheckSpreadSameExcessProperty.ts, 2, 32)) +>excessProperty : Symbol(excessProperty, Decl(excessPropertyCheckSpreadSameExcessProperty.ts, 2, 40)) + +const a1 : MyObj = { +>a1 : Symbol(a1, Decl(excessPropertyCheckSpreadSameExcessProperty.ts, 4, 5)) +>MyObj : Symbol(MyObj, Decl(excessPropertyCheckSpreadSameExcessProperty.ts, 0, 0)) + + foo: 1, +>foo : Symbol(foo, Decl(excessPropertyCheckSpreadSameExcessProperty.ts, 4, 20)) + + bar: 1, +>bar : Symbol(bar, Decl(excessPropertyCheckSpreadSameExcessProperty.ts, 5, 11)) + + ...containsExcessProperty, +>containsExcessProperty : Symbol(containsExcessProperty, Decl(excessPropertyCheckSpreadSameExcessProperty.ts, 2, 5)) + + ...{ bar: 2, excessProperty: "A" }, +>bar : Symbol(bar, Decl(excessPropertyCheckSpreadSameExcessProperty.ts, 8, 8)) +>excessProperty : Symbol(excessProperty, Decl(excessPropertyCheckSpreadSameExcessProperty.ts, 8, 16)) + +}; + +// no EPC errors because the inline excessProperty will be overwritten +const a2 : MyObj = { +>a2 : Symbol(a2, Decl(excessPropertyCheckSpreadSameExcessProperty.ts, 12, 5)) +>MyObj : Symbol(MyObj, Decl(excessPropertyCheckSpreadSameExcessProperty.ts, 0, 0)) + + foo: 1, +>foo : Symbol(foo, Decl(excessPropertyCheckSpreadSameExcessProperty.ts, 12, 20)) + + ...{ bar: 2, excessProperty: "A" }, +>bar : Symbol(bar, Decl(excessPropertyCheckSpreadSameExcessProperty.ts, 14, 8)) +>excessProperty : Symbol(excessProperty, Decl(excessPropertyCheckSpreadSameExcessProperty.ts, 14, 16)) + + ...containsExcessProperty, +>containsExcessProperty : Symbol(containsExcessProperty, Decl(excessPropertyCheckSpreadSameExcessProperty.ts, 2, 5)) + + bar: 1, +>bar : Symbol(bar, Decl(excessPropertyCheckSpreadSameExcessProperty.ts, 15, 30)) + +}; + +// no EPC errors because the inline excessProperty will be overwritten +const a3 : MyObj = { +>a3 : Symbol(a3, Decl(excessPropertyCheckSpreadSameExcessProperty.ts, 20, 5)) +>MyObj : Symbol(MyObj, Decl(excessPropertyCheckSpreadSameExcessProperty.ts, 0, 0)) + + foo: 1, +>foo : Symbol(foo, Decl(excessPropertyCheckSpreadSameExcessProperty.ts, 20, 20)) + + ...{ bar: 2, excessProperty: "A" }, +>bar : Symbol(bar, Decl(excessPropertyCheckSpreadSameExcessProperty.ts, 22, 8)) +>excessProperty : Symbol(excessProperty, Decl(excessPropertyCheckSpreadSameExcessProperty.ts, 22, 16)) + + ...containsExcessProperty, +>containsExcessProperty : Symbol(containsExcessProperty, Decl(excessPropertyCheckSpreadSameExcessProperty.ts, 2, 5)) + +}; diff --git a/tests/baselines/reference/excessPropertyCheckSpreadSameExcessProperty.types b/tests/baselines/reference/excessPropertyCheckSpreadSameExcessProperty.types new file mode 100644 index 0000000000000..f38847ce7d86d --- /dev/null +++ b/tests/baselines/reference/excessPropertyCheckSpreadSameExcessProperty.types @@ -0,0 +1,128 @@ +//// [tests/cases/compiler/excessPropertyCheckSpreadSameExcessProperty.ts] //// + +=== excessPropertyCheckSpreadSameExcessProperty.ts === +type MyObj = { foo: number; bar: number }; +>MyObj : MyObj +> : ^^^^^ +>foo : number +> : ^^^^^^ +>bar : number +> : ^^^^^^ + +const containsExcessProperty = { bar: 2, excessProperty: "A" }; +>containsExcessProperty : { bar: number; excessProperty: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ bar: 2, excessProperty: "A" } : { bar: number; excessProperty: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>bar : number +> : ^^^^^^ +>2 : 2 +> : ^ +>excessProperty : string +> : ^^^^^^ +>"A" : "A" +> : ^^^ + +const a1 : MyObj = { +>a1 : MyObj +> : ^^^^^ +>{ foo: 1, bar: 1, ...containsExcessProperty, ...{ bar: 2, excessProperty: "A" },} : { bar: number; excessProperty: string; foo: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + foo: 1, +>foo : number +> : ^^^^^^ +>1 : 1 +> : ^ + + bar: 1, +>bar : number +> : ^^^^^^ +>1 : 1 +> : ^ + + ...containsExcessProperty, +>containsExcessProperty : { bar: number; excessProperty: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + ...{ bar: 2, excessProperty: "A" }, +>{ bar: 2, excessProperty: "A" } : { bar: number; excessProperty: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>bar : number +> : ^^^^^^ +>2 : 2 +> : ^ +>excessProperty : string +> : ^^^^^^ +>"A" : "A" +> : ^^^ + +}; + +// no EPC errors because the inline excessProperty will be overwritten +const a2 : MyObj = { +>a2 : MyObj +> : ^^^^^ +>{ foo: 1, ...{ bar: 2, excessProperty: "A" }, ...containsExcessProperty, bar: 1, } : { bar: number; excessProperty: string; foo: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + foo: 1, +>foo : number +> : ^^^^^^ +>1 : 1 +> : ^ + + ...{ bar: 2, excessProperty: "A" }, +>{ bar: 2, excessProperty: "A" } : { bar: number; excessProperty: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>bar : number +> : ^^^^^^ +>2 : 2 +> : ^ +>excessProperty : string +> : ^^^^^^ +>"A" : "A" +> : ^^^ + + ...containsExcessProperty, +>containsExcessProperty : { bar: number; excessProperty: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + bar: 1, +>bar : number +> : ^^^^^^ +>1 : 1 +> : ^ + +}; + +// no EPC errors because the inline excessProperty will be overwritten +const a3 : MyObj = { +>a3 : MyObj +> : ^^^^^ +>{ foo: 1, ...{ bar: 2, excessProperty: "A" }, ...containsExcessProperty,} : { bar: number; excessProperty: string; foo: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + foo: 1, +>foo : number +> : ^^^^^^ +>1 : 1 +> : ^ + + ...{ bar: 2, excessProperty: "A" }, +>{ bar: 2, excessProperty: "A" } : { bar: number; excessProperty: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>bar : number +> : ^^^^^^ +>2 : 2 +> : ^ +>excessProperty : string +> : ^^^^^^ +>"A" : "A" +> : ^^^ + + ...containsExcessProperty, +>containsExcessProperty : { bar: number; excessProperty: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +}; diff --git a/tests/cases/compiler/excessPropertyCheckInlineChainedConditional.ts b/tests/cases/compiler/excessPropertyCheckInlineChainedConditional.ts new file mode 100644 index 0000000000000..a4e6df29082d6 --- /dev/null +++ b/tests/cases/compiler/excessPropertyCheckInlineChainedConditional.ts @@ -0,0 +1,49 @@ +// @strict: true +// @noemit: true + +declare const someConditions: boolean[]; +// bar is optional +type MyObj = { foo: number; bar?: number }; +const yWithExtraProp = { Y: 2 }; +const zWithExtraProp = { Z: 2, excessPropertyZ: "Z" }; + +const v1: MyObj = { + foo: 1, + ...(someConditions[0] + ? someConditions[1] + ? { + bar: 2, + excessPropertyA: "A", + } + : someConditions[2] + ? someConditions[3] + ? { + bar: 2, + excessPropertyB: "B", + } + : { bar: 2 } + : someConditions[4] + ? { + foo: 2, + excessPropertyC: "C", + } + : {} + : { excessPropertyD: "D" }), +}; + +// no errors by design since the objects are not defined inline +const v2: MyObj = { + ...(someConditions[0] + ? someConditions[1] + ? { bar: 2 } + : someConditions[2] + ? someConditions[3] + ? yWithExtraProp + : { bar: 2 } + : someConditions[4] + ? { foo: 2 } + : {} + : zWithExtraProp), + foo: 1, +}; + diff --git a/tests/cases/compiler/excessPropertyCheckInlineObjectWithSpreadVariable.ts b/tests/cases/compiler/excessPropertyCheckInlineObjectWithSpreadVariable.ts new file mode 100644 index 0000000000000..c60307c232ff9 --- /dev/null +++ b/tests/cases/compiler/excessPropertyCheckInlineObjectWithSpreadVariable.ts @@ -0,0 +1,24 @@ +// @strict: true +// @noemit: true + +type Foo = { + foo: string; +} + +type Bar = { + extraProp: string; +} + +const bar: Bar = { extraProp: "" }; + +const foo: Foo = { bar: "", foo: "" }; +const foo2: Foo = { ...bar, foo: "" }; +const foo3: Foo = { ...{ ...bar}, foo: ""}; +const foo4: Foo = { ...{ bar: "" }, foo: ""}; + + +const noBar = { extraProp2: "" }; +const foo5: Foo = { extraProp2: "", foo: "" }; +const foo6: Foo = { ...noBar, foo: "" }; +const foo7: Foo = { ...{ ...noBar}, foo: ""}; +const foo8: Foo = { ...{ noBar: "" }, foo: ""}; diff --git a/tests/cases/compiler/excessPropertyCheckSpreadConditionalInlineObject.ts b/tests/cases/compiler/excessPropertyCheckSpreadConditionalInlineObject.ts new file mode 100644 index 0000000000000..0aae23b82955c --- /dev/null +++ b/tests/cases/compiler/excessPropertyCheckSpreadConditionalInlineObject.ts @@ -0,0 +1,67 @@ +// @strict: true +// @noemit: true + +declare const someCondition: boolean; + +// bar is optional +type C = { foo: number; bar?: number }; + +const c: C = { + foo: 1, + ...(someCondition + ? { + bar: 2, + excessProperty: 3, + } + : {}), +}; + +const c2 = { + foo: 1, + ...(someCondition + ? { + bar: 2, + excessProperty: 3, + } + : {}), +} satisfies C; + +function testC(condition: boolean) { + return someCondition ? { bar: 2, excessProperty: 3 } : {}; +} + +// no errors on c3 and c4 since not defined inline +const c3: C = { + foo: 1, + ...testC(someCondition) +}; + +const c4 = { + foo: 1, + ...testC(someCondition) +} satisfies C; + + + +// bar is not optional +type D = { foo: number; bar: number }; + +const d: D = { + foo: 1, + ...(someCondition + ? { + bar: 2, + excessProperty: 3, + } + : {}), +}; + +const d2 = { + foo: 1, + ...(someCondition + ? { + bar: 2, + excessProperty: 3, + } + : {}), +} satisfies D; \ No newline at end of file diff --git a/tests/cases/compiler/excessPropertyCheckSpreadFunctionParam.ts b/tests/cases/compiler/excessPropertyCheckSpreadFunctionParam.ts new file mode 100644 index 0000000000000..68e11b8ee700b --- /dev/null +++ b/tests/cases/compiler/excessPropertyCheckSpreadFunctionParam.ts @@ -0,0 +1,41 @@ +// @strict: true +// @noemit: true + +type Params = { + a?: any; + b?: any; +} + +function f(params: Params) { + return; +} + +const objWithAllowedKeys = { a: 2 } +const objWithForbiddenKeys = { c: 2 } +const objWithNoKeys = {} +const a = 2; +const c = 2; + +f({ ...objWithAllowedKeys }) +f({ ...objWithForbiddenKeys }) +f({ ...objWithAllowedKeys, ...objWithForbiddenKeys }) + +f({ ...{ a: 2 }, ...{ c: 2 } }) +f({ ...{ a: 2, c: 2 } }) +f({ ...{ c: 2 }, ...{ b: 2 } }) + +f({ ...{ a: 2 }, ...objWithForbiddenKeys }) + +f({ ...{ c: 2 }, ...objWithAllowedKeys }) +f({ ...{ c: 2 }, ...objWithForbiddenKeys }) +f({ ...{ c: 2 }, ...objWithNoKeys }) + +f({ ...{...{ c: 2 }, ...objWithNoKeys } }) + +f({ a, ...{ c: 2 } }) +f({ a, ...{ c } }) +f({ ...{ c }, ...objWithAllowedKeys }) + + + + diff --git a/tests/cases/compiler/excessPropertyCheckSpreadInlineObject.ts b/tests/cases/compiler/excessPropertyCheckSpreadInlineObject.ts new file mode 100644 index 0000000000000..7592dd50d3a17 --- /dev/null +++ b/tests/cases/compiler/excessPropertyCheckSpreadInlineObject.ts @@ -0,0 +1,20 @@ +// @strict: true +// @noemit: true + +type MyObject = { foo: number; bar?: number }; + +const b: MyObject = { + foo: 1, + ...{ + bar: 2, + excessProperty: 3, + }, +}; + +const b2 = { + foo: 1, + ...{ + bar: 2, + excessProperty: 3, + }, +} satisfies MyObject; \ No newline at end of file diff --git a/tests/cases/compiler/excessPropertyCheckSpreadReturn.ts b/tests/cases/compiler/excessPropertyCheckSpreadReturn.ts new file mode 100644 index 0000000000000..55360e2632247 --- /dev/null +++ b/tests/cases/compiler/excessPropertyCheckSpreadReturn.ts @@ -0,0 +1,68 @@ +// @strict: true +// @noemit: true + +type FReturnType = { + a?: any; + b?: any; +} +const objWithAllowedKeys = { a: 2 } +const objWithForbiddenKeys = { c: 2 } +const objWithNoKeys = {} +const a = 2; +const c = 2; + +function f1(): FReturnType { + return { ...objWithAllowedKeys }; +} + +function f2(): FReturnType { + return { ...objWithForbiddenKeys }; +} + +function f3(): FReturnType { + return { ...objWithAllowedKeys, ...objWithForbiddenKeys }; +} + +function f4(): FReturnType { + return { ...{ a: 2 }, ...{ c: 2 } }; +} + +function f5(): FReturnType { + return { ...{ a: 2, c: 2 } }; +} + +function f6(): FReturnType { + return { ...{ c: 2 }, ...{ b: 2 } }; +} + +function f7(): FReturnType { + return { ...{ a: 2 }, ...objWithForbiddenKeys }; +} + +function f8(): FReturnType { + return { ...{ c: 2 }, ...objWithAllowedKeys }; +} + +function f9(): FReturnType { + return { ...{ c: 2 }, ...objWithForbiddenKeys }; +} + +function f10(): FReturnType { + return { ...{ c: 2 }, ...objWithNoKeys }; +} + +function f11(): FReturnType { + return { ...{...{ c: 2 }, ...objWithNoKeys } }; +} + +function f12(): FReturnType { + return { a, ...{ c: 2 } }; +} + +function f13(): FReturnType { + return { a, ...{ c } }; +} + +function f14(): FReturnType { + return { ...{ c }, ...objWithAllowedKeys }; +} diff --git a/tests/cases/compiler/excessPropertyCheckSpreadSameExcessProperty.ts b/tests/cases/compiler/excessPropertyCheckSpreadSameExcessProperty.ts new file mode 100644 index 0000000000000..2a5ad3ba91ce0 --- /dev/null +++ b/tests/cases/compiler/excessPropertyCheckSpreadSameExcessProperty.ts @@ -0,0 +1,28 @@ +// @strict: true +// @noemit: true + +type MyObj = { foo: number; bar: number }; + +const containsExcessProperty = { bar: 2, excessProperty: "A" }; + +const a1 : MyObj = { + foo: 1, + bar: 1, + ...containsExcessProperty, + ...{ bar: 2, excessProperty: "A" }, +}; + +// no EPC errors because the inline excessProperty will be overwritten +const a2 : MyObj = { + foo: 1, + ...{ bar: 2, excessProperty: "A" }, + ...containsExcessProperty, + bar: 1, +}; + +// no EPC errors because the inline excessProperty will be overwritten +const a3 : MyObj = { + foo: 1, + ...{ bar: 2, excessProperty: "A" }, + ...containsExcessProperty, +}; \ No newline at end of file