diff --git a/internal/checker/checker.go b/internal/checker/checker.go index c23d77a906..3cd5a2b17e 100644 --- a/internal/checker/checker.go +++ b/internal/checker/checker.go @@ -15884,6 +15884,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 } @@ -17004,7 +17019,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..6d30508a2a --- /dev/null +++ b/testdata/baselines/reference/submodule/conformance/destructuringParameterDeclaration9(strict=true).errors.txt @@ -0,0 +1,58 @@ +index.js(7,9): error TS7031: Binding element 'json' implicitly has an 'any[]' type. +index.js(15,9): error TS7031: Binding element 'json' implicitly has an 'any[]' type. +index.js(37,20): error TS7031: Binding element 'json' implicitly has an 'any[]' type. +index.js(42,15): error TS7031: Binding element 'json' implicitly has an 'any[]' type. + + +==== index.js (4 errors) ==== + /** + * @param {Object} [config] + * @param {Partial>} [config.additionalFiles] + */ + export function prepareConfig({ + additionalFiles: { + json = [] + ~~~~ +!!! error TS7031: Binding element 'json' implicitly has an 'any[]' type. + } = {} + } = {}) { + 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 } + ~~~~ +!!! error TS7031: Binding element 'json' implicitly has an 'any[]' type. + + /** + * @param {[[string[]?]?]} [x] + */ + function f2([[json = []] = []] = []) { return json } + ~~~~ +!!! error TS7031: Binding element 'json' implicitly has an 'any[]' type. + \ 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 d91371d03a..046b7be9ed 100644 --- a/testdata/baselines/reference/submodule/conformance/destructuringParameterDeclaration9(strict=true).types +++ b/testdata/baselines/reference/submodule/conformance/destructuringParameterDeclaration9(strict=true).types @@ -12,7 +12,7 @@ export function prepareConfig({ >additionalFiles : any json = [] ->json : never[] +>json : any[] >[] : never[] } = {} @@ -22,7 +22,7 @@ export function prepareConfig({ >{} : {} json // string[] ->json : never[] +>json : any[] } export function prepareConfigWithoutAnnotation({ @@ -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: { @@ -75,22 +75,22 @@ export const prepareConfigWithContextualSignature = ({ * @param {{ a?: { json?: string[] }}} [config] */ function f1({ a: { json = [] } = {} } = {}) { return json } ->f1 : ({ a: { json } }?: { a?: { json?: never[] | undefined; } | undefined; }) => never[] +>f1 : ({ a: { json } }?: { a?: { json?: never[] | undefined; } | undefined; }) => any[] >a : any ->json : never[] +>json : any[] >[] : never[] >{} : {} >{} : {} ->json : never[] +>json : any[] /** * @param {[[string[]?]?]} [x] */ function f2([[json = []] = []] = []) { return json } ->f2 : ([[json]]?: [([(never[] | undefined)?] | undefined)?]) => never[] ->json : never[] +>f2 : ([[json]]?: [([(never[] | undefined)?] | undefined)?]) => any[] +>json : any[] >[] : never[] >[] : [] >[] : [] ->json : never[] +>json : any[] 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 index b9f791b326..36928d71bb 100644 --- a/testdata/baselines/reference/submoduleAccepted/conformance/destructuringParameterDeclaration9(strict=true).errors.txt.diff +++ b/testdata/baselines/reference/submoduleAccepted/conformance/destructuringParameterDeclaration9(strict=true).errors.txt.diff @@ -1,53 +1,39 @@ --- 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(7,9): error TS7031: Binding element 'json' implicitly has an 'any[]' type. + 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 ++index.js(37,20): error TS7031: Binding element 'json' implicitly has an 'any[]' type. ++index.js(42,15): error TS7031: Binding element 'json' implicitly has an 'any[]' type. ++ ++ ++==== index.js (4 errors) ==== + /** + * @param {Object} [config] + * @param {Partial>} [config.additionalFiles] +@@= skipped -8, +11 lines =@@ + export function prepareConfig({ + additionalFiles: { + json = [] ++ ~~~~ ++!!! error TS7031: Binding element 'json' implicitly has an 'any[]' type. + } = {} + } = {}) { + json // string[] +@@= skipped -32, +34 lines =@@ + * @param {{ a?: { json?: string[] }}} [config] + */ + function f1({ a: { json = [] } = {} } = {}) { return json } ++ ~~~~ ++!!! error TS7031: Binding element 'json' implicitly has an 'any[]' type. + + /** + * @param {[[string[]?]?]} [x] + */ + function f2([[json = []] = []] = []) { return json } ++ ~~~~ ++!!! error TS7031: Binding element 'json' implicitly has an 'any[]' type. + \ 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 fad06a430c..544a17f2d3 100644 --- a/testdata/baselines/reference/submoduleAccepted/conformance/destructuringParameterDeclaration9(strict=true).types.diff +++ b/testdata/baselines/reference/submoduleAccepted/conformance/destructuringParameterDeclaration9(strict=true).types.diff @@ -12,7 +12,7 @@ json = [] ->json : string[] -+>json : never[] ++>json : any[] >[] : never[] } = {} @@ -21,28 +21,11 @@ json // string[] ->json : string[] -+>json : never[] ++>json : any[] } export function prepareConfigWithoutAnnotation({ -@@= skipped -10, +10 lines =@@ - >additionalFiles : any - - json = [] -->json : any[] -+>json : never[] - >[] : never[] - - } = {} -@@= skipped -10, +10 lines =@@ - >{} : {} - - json -->json : any[] -+>json : never[] - } - - /** @type {(param: { +@@= skipped -27, +27 lines =@@ additionalFiles?: Partial>; }) => void} */ export const prepareConfigWithContextualSignature = ({ @@ -53,20 +36,20 @@ additionalFiles: { >additionalFiles : any -@@= skipped -33, +33 lines =@@ +@@= skipped -26, +26 lines =@@ * @param {{ a?: { json?: string[] }}} [config] */ function f1({ a: { json = [] } = {} } = {}) { return json } ->f1 : ({ a: { json } }?: { a?: { json?: string[]; }; }) => string[] -+>f1 : ({ a: { json } }?: { a?: { json?: never[] | undefined; } | undefined; }) => never[] ++>f1 : ({ a: { json } }?: { a?: { json?: never[] | undefined; } | undefined; }) => any[] >a : any ->json : string[] -+>json : never[] ++>json : any[] >[] : never[] >{} : {} >{} : {} ->json : string[] -+>json : never[] ++>json : any[] /** * @param {[[string[]?]?]} [x] @@ -74,10 +57,10 @@ function f2([[json = []] = []] = []) { return json } ->f2 : ([[json]]?: [[string[]?]?]) => string[] ->json : string[] -+>f2 : ([[json]]?: [([(never[] | undefined)?] | undefined)?]) => never[] -+>json : never[] ++>f2 : ([[json]]?: [([(never[] | undefined)?] | undefined)?]) => any[] ++>json : any[] >[] : never[] >[] : [] >[] : [] ->json : string[] -+>json : never[] ++>json : any[] 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