diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5d67431022a..3e64493503c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -25281,27 +25281,28 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } else { for (const t of (type as UnionType).types) { - if (reportWideningErrorsInType(t)) { - errorReported = true; - } + errorReported ||= reportWideningErrorsInType(t); } } } - if (isArrayOrTupleType(type)) { + else if (isArrayOrTupleType(type)) { for (const t of getTypeArguments(type)) { - if (reportWideningErrorsInType(t)) { - errorReported = true; - } + errorReported ||= reportWideningErrorsInType(t); } } - if (isObjectLiteralType(type)) { + else if (isObjectLiteralType(type)) { for (const p of getPropertiesOfObjectType(type)) { const t = getTypeOfSymbol(p); if (getObjectFlags(t) & ObjectFlags.ContainsWideningType) { - if (!reportWideningErrorsInType(t)) { - error(p.valueDeclaration, Diagnostics.Object_literal_s_property_0_implicitly_has_an_1_type, symbolToString(p), typeToString(getWidenedType(t))); + errorReported = reportWideningErrorsInType(t); + if (!errorReported) { + // we need to account for property types coming from object literal type normalization in unions + const valueDeclaration = p.declarations?.find(d => d.symbol.valueDeclaration?.parent === type.symbol.valueDeclaration); + if (valueDeclaration) { + error(valueDeclaration, Diagnostics.Object_literal_s_property_0_implicitly_has_an_1_type, symbolToString(p), typeToString(getWidenedType(t))); + errorReported = true; + } } - errorReported = true; } } } diff --git a/tests/baselines/reference/noImplicitAnyUnionNormalizedObjectLiteral1.errors.txt b/tests/baselines/reference/noImplicitAnyUnionNormalizedObjectLiteral1.errors.txt new file mode 100644 index 00000000000..5aec21fd621 --- /dev/null +++ b/tests/baselines/reference/noImplicitAnyUnionNormalizedObjectLiteral1.errors.txt @@ -0,0 +1,32 @@ +noImplicitAnyUnionNormalizedObjectLiteral1.ts(16,3): error TS7018: Object literal's property 'p' implicitly has an 'any' type. +noImplicitAnyUnionNormalizedObjectLiteral1.ts(17,3): error TS7018: Object literal's property 's' implicitly has an 'any' type. + + +==== noImplicitAnyUnionNormalizedObjectLiteral1.ts (2 errors) ==== + // https://github.com/microsoft/TypeScript/issues/58150 + + function doSthWithParams(params: unknown) { + if (typeof params !== "object") { + return {}; + } + + return { + c: "foo", + p: "bar", + s: "baz", + }; + } + + const bar = { + p: null, + ~~~~~~~ +!!! error TS7018: Object literal's property 'p' implicitly has an 'any' type. + s: null, + ~~~~~~~ +!!! error TS7018: Object literal's property 's' implicitly has an 'any' type. + ...doSthWithParams({ + p: "hello", + s: "world", + }), + }; + \ No newline at end of file diff --git a/tests/baselines/reference/noImplicitAnyUnionNormalizedObjectLiteral1.symbols b/tests/baselines/reference/noImplicitAnyUnionNormalizedObjectLiteral1.symbols new file mode 100644 index 00000000000..f63d606aeb2 --- /dev/null +++ b/tests/baselines/reference/noImplicitAnyUnionNormalizedObjectLiteral1.symbols @@ -0,0 +1,49 @@ +//// [tests/cases/compiler/noImplicitAnyUnionNormalizedObjectLiteral1.ts] //// + +=== noImplicitAnyUnionNormalizedObjectLiteral1.ts === +// https://github.com/microsoft/TypeScript/issues/58150 + +function doSthWithParams(params: unknown) { +>doSthWithParams : Symbol(doSthWithParams, Decl(noImplicitAnyUnionNormalizedObjectLiteral1.ts, 0, 0)) +>params : Symbol(params, Decl(noImplicitAnyUnionNormalizedObjectLiteral1.ts, 2, 25)) + + if (typeof params !== "object") { +>params : Symbol(params, Decl(noImplicitAnyUnionNormalizedObjectLiteral1.ts, 2, 25)) + + return {}; + } + + return { + c: "foo", +>c : Symbol(c, Decl(noImplicitAnyUnionNormalizedObjectLiteral1.ts, 7, 10)) + + p: "bar", +>p : Symbol(p, Decl(noImplicitAnyUnionNormalizedObjectLiteral1.ts, 8, 13)) + + s: "baz", +>s : Symbol(s, Decl(noImplicitAnyUnionNormalizedObjectLiteral1.ts, 9, 13)) + + }; +} + +const bar = { +>bar : Symbol(bar, Decl(noImplicitAnyUnionNormalizedObjectLiteral1.ts, 14, 5)) + + p: null, +>p : Symbol(p, Decl(noImplicitAnyUnionNormalizedObjectLiteral1.ts, 14, 13)) + + s: null, +>s : Symbol(s, Decl(noImplicitAnyUnionNormalizedObjectLiteral1.ts, 15, 10)) + + ...doSthWithParams({ +>doSthWithParams : Symbol(doSthWithParams, Decl(noImplicitAnyUnionNormalizedObjectLiteral1.ts, 0, 0)) + + p: "hello", +>p : Symbol(p, Decl(noImplicitAnyUnionNormalizedObjectLiteral1.ts, 17, 22)) + + s: "world", +>s : Symbol(s, Decl(noImplicitAnyUnionNormalizedObjectLiteral1.ts, 18, 15)) + + }), +}; + diff --git a/tests/baselines/reference/noImplicitAnyUnionNormalizedObjectLiteral1.types b/tests/baselines/reference/noImplicitAnyUnionNormalizedObjectLiteral1.types new file mode 100644 index 00000000000..1cd3de5111b --- /dev/null +++ b/tests/baselines/reference/noImplicitAnyUnionNormalizedObjectLiteral1.types @@ -0,0 +1,88 @@ +//// [tests/cases/compiler/noImplicitAnyUnionNormalizedObjectLiteral1.ts] //// + +=== noImplicitAnyUnionNormalizedObjectLiteral1.ts === +// https://github.com/microsoft/TypeScript/issues/58150 + +function doSthWithParams(params: unknown) { +>doSthWithParams : (params: unknown) => { c?: undefined; p?: undefined; s?: undefined; } | { c: string; p: string; s: string; } +> : ^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>params : unknown +> : ^^^^^^^ + + if (typeof params !== "object") { +>typeof params !== "object" : boolean +> : ^^^^^^^ +>typeof params : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>params : unknown +> : ^^^^^^^ +>"object" : "object" +> : ^^^^^^^^ + + return {}; +>{} : {} +> : ^^ + } + + return { +>{ c: "foo", p: "bar", s: "baz", } : { c: string; p: string; s: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + c: "foo", +>c : string +> : ^^^^^^ +>"foo" : "foo" +> : ^^^^^ + + p: "bar", +>p : string +> : ^^^^^^ +>"bar" : "bar" +> : ^^^^^ + + s: "baz", +>s : string +> : ^^^^^^ +>"baz" : "baz" +> : ^^^^^ + + }; +} + +const bar = { +>bar : { c?: undefined; p: any; s: any; } | { c: string; p: string; s: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ p: null, s: null, ...doSthWithParams({ p: "hello", s: "world", }),} : { c?: undefined; p: null; s: null; } | { c: string; p: string; s: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + p: null, +>p : null +> : ^^^^ + + s: null, +>s : null +> : ^^^^ + + ...doSthWithParams({ +>doSthWithParams({ p: "hello", s: "world", }) : { c?: undefined; p?: undefined; s?: undefined; } | { c: string; p: string; s: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>doSthWithParams : (params: unknown) => { c?: undefined; p?: undefined; s?: undefined; } | { c: string; p: string; s: string; } +> : ^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ p: "hello", s: "world", } : { p: string; s: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ + + p: "hello", +>p : string +> : ^^^^^^ +>"hello" : "hello" +> : ^^^^^^^ + + s: "world", +>s : string +> : ^^^^^^ +>"world" : "world" +> : ^^^^^^^ + + }), +}; + diff --git a/tests/cases/compiler/noImplicitAnyUnionNormalizedObjectLiteral1.ts b/tests/cases/compiler/noImplicitAnyUnionNormalizedObjectLiteral1.ts new file mode 100644 index 00000000000..308eef6fc7a --- /dev/null +++ b/tests/cases/compiler/noImplicitAnyUnionNormalizedObjectLiteral1.ts @@ -0,0 +1,26 @@ +// @strictNullChecks: false +// @noImplicitAny: true +// @noEmit: true + +// https://github.com/microsoft/TypeScript/issues/58150 + +function doSthWithParams(params: unknown) { + if (typeof params !== "object") { + return {}; + } + + return { + c: "foo", + p: "bar", + s: "baz", + }; +} + +const bar = { + p: null, + s: null, + ...doSthWithParams({ + p: "hello", + s: "world", + }), +};