diff --git a/internal/checker/checker.go b/internal/checker/checker.go index 887bd0ed25..ca4dd45f4a 100644 --- a/internal/checker/checker.go +++ b/internal/checker/checker.go @@ -16092,6 +16092,21 @@ func (c *Checker) padTupleType(t *Type, pattern *ast.Node) *Type { } func (c *Checker) widenTypeInferredFromInitializer(declaration *ast.Node, t *Type) *Type { + widened := c.getWidenedLiteralTypeForInitializer(declaration, t) + if ast.IsInJSFile(declaration) { + if c.isEmptyLiteralType(widened) { + c.reportImplicitAny(declaration, c.anyType, WideningKindNormal) + return c.anyType + } + if c.isEmptyArrayLiteralType(widened) { + c.reportImplicitAny(declaration, c.anyArrayType, WideningKindNormal) + return c.anyArrayType + } + } + return widened +} + +func (c *Checker) getWidenedLiteralTypeForInitializer(declaration *ast.Node, t *Type) *Type { if c.getCombinedNodeFlagsCached(declaration)&ast.NodeFlagsConstant != 0 || isDeclarationReadonly(declaration) { return t } @@ -17212,7 +17227,7 @@ func (c *Checker) getTypeFromBindingElement(element *ast.Node, includePatternInT if ast.IsBindingPattern(element.Name()) { contextualType = c.getTypeFromBindingPattern(element.Name(), true /*includePatternInType*/, false /*reportErrors*/) } - return c.addOptionality(c.widenTypeInferredFromInitializer(element, c.checkDeclarationInitializer(element, CheckModeNormal, contextualType))) + return c.addOptionality(c.getWidenedLiteralTypeForInitializer(element, c.checkDeclarationInitializer(element, CheckModeNormal, contextualType))) } if ast.IsBindingPattern(element.Name()) { return c.getTypeFromBindingPattern(element.Name(), includePatternInType, reportErrors) diff --git a/testdata/baselines/reference/submodule/conformance/destructuringParameterDeclaration9(strict=true).errors.txt b/testdata/baselines/reference/submodule/conformance/destructuringParameterDeclaration9(strict=true).errors.txt new file mode 100644 index 0000000000..6f0315e559 --- /dev/null +++ b/testdata/baselines/reference/submodule/conformance/destructuringParameterDeclaration9(strict=true).errors.txt @@ -0,0 +1,49 @@ +index.js(15,9): error TS7031: Binding element 'json' implicitly has an 'any[]' type. + + +==== index.js (1 errors) ==== + /** + * @param {Object} [config] + * @param {Partial>} [config.additionalFiles] + */ + export function prepareConfig({ + additionalFiles: { + json = [] + } = {} + } = {}) { + json // string[] + } + + export function prepareConfigWithoutAnnotation({ + additionalFiles: { + json = [] + ~~~~ +!!! error TS7031: Binding element 'json' implicitly has an 'any[]' type. + } = {} + } = {}) { + json + } + + /** @type {(param: { + additionalFiles?: Partial>; + }) => void} */ + export const prepareConfigWithContextualSignature = ({ + additionalFiles: { + json = [] + } = {} + } = {})=> { + json // string[] + } + + // Additional repros from https://github.com/microsoft/TypeScript/issues/59936 + + /** + * @param {{ a?: { json?: string[] }}} [config] + */ + function f1({ a: { json = [] } = {} } = {}) { return json } + + /** + * @param {[[string[]?]?]} [x] + */ + function f2([[json = []] = []] = []) { return json } + \ No newline at end of file diff --git a/testdata/baselines/reference/submodule/conformance/destructuringParameterDeclaration9(strict=true).types b/testdata/baselines/reference/submodule/conformance/destructuringParameterDeclaration9(strict=true).types index be0248f5ee..bc46e80048 100644 --- a/testdata/baselines/reference/submodule/conformance/destructuringParameterDeclaration9(strict=true).types +++ b/testdata/baselines/reference/submodule/conformance/destructuringParameterDeclaration9(strict=true).types @@ -32,7 +32,7 @@ export function prepareConfigWithoutAnnotation({ >additionalFiles : any json = [] ->json : never[] +>json : any[] >[] : never[] } = {} @@ -42,7 +42,7 @@ export function prepareConfigWithoutAnnotation({ >{} : {} json ->json : never[] +>json : any[] } /** @type {(param: { diff --git a/testdata/baselines/reference/submodule/conformance/typeFromJSInitializer.errors.txt b/testdata/baselines/reference/submodule/conformance/typeFromJSInitializer.errors.txt index ecf3829086..ed898025a1 100644 --- a/testdata/baselines/reference/submodule/conformance/typeFromJSInitializer.errors.txt +++ b/testdata/baselines/reference/submodule/conformance/typeFromJSInitializer.errors.txt @@ -1,15 +1,14 @@ a.js(7,9): error TS7009: 'new' expression, whose target lacks a construct signature, implicitly has an 'any' type. +a.js(25,29): error TS7006: Parameter 'l' implicitly has an 'any[]' type. a.js(27,5): error TS2322: Type 'undefined' is not assignable to type 'null'. a.js(29,5): error TS2322: Type '1' is not assignable to type 'null'. a.js(30,5): error TS2322: Type 'true' is not assignable to type 'null'. a.js(31,5): error TS2322: Type '{}' is not assignable to type 'null'. a.js(32,5): error TS2322: Type '"ok"' is not assignable to type 'null'. a.js(37,5): error TS2322: Type 'string' is not assignable to type 'number'. -a.js(40,12): error TS2345: Argument of type '1' is not assignable to parameter of type 'never'. -a.js(41,12): error TS2345: Argument of type '"ok"' is not assignable to parameter of type 'never'. -==== a.js (9 errors) ==== +==== a.js (8 errors) ==== function A () { // should get any on this-assignments in constructor this.unknown = null @@ -37,6 +36,8 @@ a.js(41,12): error TS2345: Argument of type '"ok"' is not assignable to paramete // should get any on parameter initialisers function f(a = null, b = n, l = []) { + ~~~~~~ +!!! error TS7006: Parameter 'l' implicitly has an 'any[]' type. // a should be null in strict mode a = undefined ~ @@ -64,11 +65,7 @@ a.js(41,12): error TS2345: Argument of type '"ok"' is not assignable to paramete // l should be any[] l.push(1) - ~ -!!! error TS2345: Argument of type '1' is not assignable to parameter of type 'never'. l.push('ok') - ~~~~ -!!! error TS2345: Argument of type '"ok"' is not assignable to parameter of type 'never'. } // should get any on variable initialisers diff --git a/testdata/baselines/reference/submodule/conformance/typeFromJSInitializer.types b/testdata/baselines/reference/submodule/conformance/typeFromJSInitializer.types index dbcb1afd01..ef129d6f2d 100644 --- a/testdata/baselines/reference/submodule/conformance/typeFromJSInitializer.types +++ b/testdata/baselines/reference/submodule/conformance/typeFromJSInitializer.types @@ -128,11 +128,11 @@ var n; // should get any on parameter initialisers function f(a = null, b = n, l = []) { ->f : (a?: null, b?: number | undefined, l?: never[]) => void +>f : (a?: null, b?: number | undefined, l?: any[]) => void >a : null >b : number | undefined >n : number | undefined ->l : never[] +>l : any[] >[] : never[] // a should be null in strict mode @@ -184,16 +184,16 @@ function f(a = null, b = n, l = []) { // l should be any[] l.push(1) >l.push(1) : number ->l.push : (...items: never[]) => number ->l : never[] ->push : (...items: never[]) => number +>l.push : (...items: any[]) => number +>l : any[] +>push : (...items: any[]) => number >1 : 1 l.push('ok') >l.push('ok') : number ->l.push : (...items: never[]) => number ->l : never[] ->push : (...items: never[]) => number +>l.push : (...items: any[]) => number +>l : any[] +>push : (...items: any[]) => number >'ok' : "ok" } diff --git a/testdata/baselines/reference/submoduleAccepted/conformance/destructuringParameterDeclaration9(strict=true).errors.txt.diff b/testdata/baselines/reference/submoduleAccepted/conformance/destructuringParameterDeclaration9(strict=true).errors.txt.diff deleted file mode 100644 index b9f791b326..0000000000 --- a/testdata/baselines/reference/submoduleAccepted/conformance/destructuringParameterDeclaration9(strict=true).errors.txt.diff +++ /dev/null @@ -1,53 +0,0 @@ ---- old.destructuringParameterDeclaration9(strict=true).errors.txt -+++ new.destructuringParameterDeclaration9(strict=true).errors.txt -@@= skipped -0, +0 lines =@@ --index.js(15,9): error TS7031: Binding element 'json' implicitly has an 'any[]' type. -- -- --==== index.js (1 errors) ==== -- /** -- * @param {Object} [config] -- * @param {Partial>} [config.additionalFiles] -- */ -- export function prepareConfig({ -- additionalFiles: { -- json = [] -- } = {} -- } = {}) { -- json // string[] -- } -- -- export function prepareConfigWithoutAnnotation({ -- additionalFiles: { -- json = [] -- ~~~~ --!!! error TS7031: Binding element 'json' implicitly has an 'any[]' type. -- } = {} -- } = {}) { -- json -- } -- -- /** @type {(param: { -- additionalFiles?: Partial>; -- }) => void} */ -- export const prepareConfigWithContextualSignature = ({ -- additionalFiles: { -- json = [] -- } = {} -- } = {})=> { -- json // string[] -- } -- -- // Additional repros from https://github.com/microsoft/TypeScript/issues/59936 -- -- /** -- * @param {{ a?: { json?: string[] }}} [config] -- */ -- function f1({ a: { json = [] } = {} } = {}) { return json } -- -- /** -- * @param {[[string[]?]?]} [x] -- */ -- function f2([[json = []] = []] = []) { return json } -- -+ \ No newline at end of file diff --git a/testdata/baselines/reference/submoduleAccepted/conformance/destructuringParameterDeclaration9(strict=true).types.diff b/testdata/baselines/reference/submoduleAccepted/conformance/destructuringParameterDeclaration9(strict=true).types.diff index 23b183f260..0e5282cd84 100644 --- a/testdata/baselines/reference/submoduleAccepted/conformance/destructuringParameterDeclaration9(strict=true).types.diff +++ b/testdata/baselines/reference/submoduleAccepted/conformance/destructuringParameterDeclaration9(strict=true).types.diff @@ -9,24 +9,7 @@ additionalFiles: { >additionalFiles : any -@@= skipped -26, +26 lines =@@ - >additionalFiles : any - - json = [] -->json : any[] -+>json : never[] - >[] : never[] - - } = {} -@@= skipped -10, +10 lines =@@ - >{} : {} - - json -->json : any[] -+>json : never[] - } - - /** @type {(param: { +@@= skipped -43, +43 lines =@@ additionalFiles?: Partial>; }) => void} */ export const prepareConfigWithContextualSignature = ({ @@ -37,7 +20,7 @@ additionalFiles: { >additionalFiles : any -@@= skipped -33, +33 lines =@@ +@@= skipped -26, +26 lines =@@ * @param {{ a?: { json?: string[] }}} [config] */ function f1({ a: { json = [] } = {} } = {}) { return json } diff --git a/testdata/baselines/reference/submoduleAccepted/conformance/typeFromJSInitializer.errors.txt.diff b/testdata/baselines/reference/submoduleAccepted/conformance/typeFromJSInitializer.errors.txt.diff index 3e5a382d14..881af72565 100644 --- a/testdata/baselines/reference/submoduleAccepted/conformance/typeFromJSInitializer.errors.txt.diff +++ b/testdata/baselines/reference/submoduleAccepted/conformance/typeFromJSInitializer.errors.txt.diff @@ -4,22 +4,16 @@ -a.js(3,5): error TS7008: Member 'unknown' implicitly has an 'any' type. -a.js(4,5): error TS7008: Member 'unknowable' implicitly has an 'any' type. -a.js(5,5): error TS7008: Member 'empty' implicitly has an 'any[]' type. --a.js(25,29): error TS7006: Parameter 'l' implicitly has an 'any[]' type. +a.js(7,9): error TS7009: 'new' expression, whose target lacks a construct signature, implicitly has an 'any' type. + a.js(25,29): error TS7006: Parameter 'l' implicitly has an 'any[]' type. a.js(27,5): error TS2322: Type 'undefined' is not assignable to type 'null'. a.js(29,5): error TS2322: Type '1' is not assignable to type 'null'. - a.js(30,5): error TS2322: Type 'true' is not assignable to type 'null'. - a.js(31,5): error TS2322: Type '{}' is not assignable to type 'null'. - a.js(32,5): error TS2322: Type '"ok"' is not assignable to type 'null'. +@@= skipped -9, +7 lines =@@ a.js(37,5): error TS2322: Type 'string' is not assignable to type 'number'. -- -- + + -==== a.js (10 errors) ==== -+a.js(40,12): error TS2345: Argument of type '1' is not assignable to parameter of type 'never'. -+a.js(41,12): error TS2345: Argument of type '"ok"' is not assignable to parameter of type 'never'. -+ -+ -+==== a.js (9 errors) ==== ++==== a.js (8 errors) ==== function A () { // should get any on this-assignments in constructor this.unknown = null @@ -37,25 +31,4 @@ +!!! error TS7009: 'new' expression, whose target lacks a construct signature, implicitly has an 'any' type. a.unknown = 1 a.unknown = true - a.unknown = {} -@@= skipped -41, +36 lines =@@ - - // should get any on parameter initialisers - function f(a = null, b = n, l = []) { -- ~~~~~~ --!!! error TS7006: Parameter 'l' implicitly has an 'any[]' type. - // a should be null in strict mode - a = undefined - ~ -@@= skipped -29, +27 lines =@@ - - // l should be any[] - l.push(1) -+ ~ -+!!! error TS2345: Argument of type '1' is not assignable to parameter of type 'never'. - l.push('ok') -+ ~~~~ -+!!! error TS2345: Argument of type '"ok"' is not assignable to parameter of type 'never'. - } - - // should get any on variable initialisers \ No newline at end of file + a.unknown = {} \ No newline at end of file diff --git a/testdata/baselines/reference/submoduleAccepted/conformance/typeFromJSInitializer.types.diff b/testdata/baselines/reference/submoduleAccepted/conformance/typeFromJSInitializer.types.diff index 2529a74db4..302ab6f208 100644 --- a/testdata/baselines/reference/submoduleAccepted/conformance/typeFromJSInitializer.types.diff +++ b/testdata/baselines/reference/submoduleAccepted/conformance/typeFromJSInitializer.types.diff @@ -163,40 +163,4 @@ +>push : any >'hi' : "hi" - /** @type {number | undefined} */ -@@= skipped -126, +126 lines =@@ - - // should get any on parameter initialisers - function f(a = null, b = n, l = []) { -->f : (a?: null, b?: number | undefined, l?: any[]) => void -+>f : (a?: null, b?: number | undefined, l?: never[]) => void - >a : null - >b : number | undefined - >n : number | undefined -->l : any[] -+>l : never[] - >[] : never[] - - // a should be null in strict mode -@@= skipped -56, +56 lines =@@ - // l should be any[] - l.push(1) - >l.push(1) : number -->l.push : (...items: any[]) => number -->l : any[] -->push : (...items: any[]) => number -+>l.push : (...items: never[]) => number -+>l : never[] -+>push : (...items: never[]) => number - >1 : 1 - - l.push('ok') - >l.push('ok') : number -->l.push : (...items: any[]) => number -->l : any[] -->push : (...items: any[]) => number -+>l.push : (...items: never[]) => number -+>l : never[] -+>push : (...items: never[]) => number - >'ok' : "ok" - } + /** @type {number | undefined} */ \ No newline at end of file