From 7c893fec0ea9ff2d9298f36937863a0ef24f5e67 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 27 Sep 2024 06:47:53 -0700 Subject: [PATCH 1/4] No widening errors when obtaining implied binding pattern type --- src/compiler/checker.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index dbe53a978c6ed..0ed70c4df4e03 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11943,7 +11943,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // contextual type or, if the element itself is a binding pattern, with the type implied by that binding // pattern. const contextualType = isBindingPattern(element.name) ? getTypeFromBindingPattern(element.name, /*includePatternInType*/ true, /*reportErrors*/ false) : unknownType; - return addOptionality(widenTypeInferredFromInitializer(element, checkDeclarationInitializer(element, CheckMode.Normal, contextualType))); + return addOptionality(getWidenedLiteralTypeForInitializer(element, checkDeclarationInitializer(element, CheckMode.Normal, contextualType))); } if (isBindingPattern(element.name)) { return getTypeFromBindingPattern(element.name, includePatternInType, reportErrors); @@ -40770,7 +40770,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function widenTypeInferredFromInitializer(declaration: HasExpressionInitializer, type: Type) { - const widened = getCombinedNodeFlagsCached(declaration) & NodeFlags.Constant || isDeclarationReadonly(declaration) ? type : getWidenedLiteralType(type); + const widened = getWidenedLiteralTypeForInitializer(declaration, type) if (isInJSFile(declaration)) { if (isEmptyLiteralType(widened)) { reportImplicitAny(declaration, anyType); @@ -40784,6 +40784,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return widened; } + function getWidenedLiteralTypeForInitializer(declaration: HasExpressionInitializer, type: Type) { + return getCombinedNodeFlagsCached(declaration) & NodeFlags.Constant || isDeclarationReadonly(declaration) ? type : getWidenedLiteralType(type); + } + function isLiteralOfContextualType(candidateType: Type, contextualType: Type | undefined): boolean { if (contextualType) { if (contextualType.flags & TypeFlags.UnionOrIntersection) { From 8ee94a9d401737b3ec9afa7a29737f81aa8aba4c Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 27 Sep 2024 07:01:04 -0700 Subject: [PATCH 2/4] Add tests --- .../destructuringParameterDeclaration10.ts | 30 +++++++++++ .../destructuringParameterDeclaration9.ts | 51 +++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration10.ts create mode 100644 tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration9.ts diff --git a/tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration10.ts b/tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration10.ts new file mode 100644 index 0000000000000..997341c7cb1a6 --- /dev/null +++ b/tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration10.ts @@ -0,0 +1,30 @@ +// @strict: true, false +// @noEmit: true + +export function prepareConfig({ + additionalFiles: { + json = [] + } = {} +}: { + additionalFiles?: Partial>; +} = {}) { + json // string[] +} + +export function prepareConfigWithoutAnnotation({ + additionalFiles: { + json = [] + } = {} +} = {}) { + json +} + +export const prepareConfigWithContextualSignature: (param:{ + additionalFiles?: Partial>; +}) => void = ({ + additionalFiles: { + json = [] + } = {} +} = {}) => { + json // string[] +} diff --git a/tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration9.ts b/tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration9.ts new file mode 100644 index 0000000000000..d033af2b0891e --- /dev/null +++ b/tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration9.ts @@ -0,0 +1,51 @@ +// @strict: true, false +// @noEmit: true +// @allowJs: true +// @checkJs: true + +// https://github.com/microsoft/TypeScript/issues/59936 + +// @filename: index.js + +/** + * @param {Object} [config] + * @param {Partial>} [config.additionalFiles] + */ +export function prepareConfig({ + additionalFiles: { + json = [] + } = {} +} = {}) { + json // string[] +} + +export function prepareConfigWithoutAnnotation({ + additionalFiles: { + json = [] + } = {} +} = {}) { + 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 } From 39364eed3a1c30b417f17e314cd9aa22bfa46514 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 27 Sep 2024 07:01:13 -0700 Subject: [PATCH 3/4] Accept new baselines --- ...rameterDeclaration10(strict=false).symbols | 61 ++++++++ ...ParameterDeclaration10(strict=false).types | 99 +++++++++++++ ...arameterDeclaration10(strict=true).symbols | 61 ++++++++ ...gParameterDeclaration10(strict=true).types | 99 +++++++++++++ ...arameterDeclaration9(strict=false).symbols | 74 ++++++++++ ...gParameterDeclaration9(strict=false).types | 131 ++++++++++++++++++ ...ameterDeclaration9(strict=true).errors.txt | 49 +++++++ ...ParameterDeclaration9(strict=true).symbols | 71 ++++++++++ ...ngParameterDeclaration9(strict=true).types | 131 ++++++++++++++++++ 9 files changed, 776 insertions(+) create mode 100644 tests/baselines/reference/destructuringParameterDeclaration10(strict=false).symbols create mode 100644 tests/baselines/reference/destructuringParameterDeclaration10(strict=false).types create mode 100644 tests/baselines/reference/destructuringParameterDeclaration10(strict=true).symbols create mode 100644 tests/baselines/reference/destructuringParameterDeclaration10(strict=true).types create mode 100644 tests/baselines/reference/destructuringParameterDeclaration9(strict=false).symbols create mode 100644 tests/baselines/reference/destructuringParameterDeclaration9(strict=false).types create mode 100644 tests/baselines/reference/destructuringParameterDeclaration9(strict=true).errors.txt create mode 100644 tests/baselines/reference/destructuringParameterDeclaration9(strict=true).symbols create mode 100644 tests/baselines/reference/destructuringParameterDeclaration9(strict=true).types diff --git a/tests/baselines/reference/destructuringParameterDeclaration10(strict=false).symbols b/tests/baselines/reference/destructuringParameterDeclaration10(strict=false).symbols new file mode 100644 index 0000000000000..a0da095b3f6de --- /dev/null +++ b/tests/baselines/reference/destructuringParameterDeclaration10(strict=false).symbols @@ -0,0 +1,61 @@ +//// [tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration10.ts] //// + +=== destructuringParameterDeclaration10.ts === +export function prepareConfig({ +>prepareConfig : Symbol(prepareConfig, Decl(destructuringParameterDeclaration10.ts, 0, 0)) + + additionalFiles: { +>additionalFiles : Symbol(additionalFiles, Decl(destructuringParameterDeclaration10.ts, 4, 4)) + + json = [] +>json : Symbol(json, Decl(destructuringParameterDeclaration10.ts, 1, 22)) + + } = {} +}: { + additionalFiles?: Partial>; +>additionalFiles : Symbol(additionalFiles, Decl(destructuringParameterDeclaration10.ts, 4, 4)) +>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) + +} = {}) { + json // string[] +>json : Symbol(json, Decl(destructuringParameterDeclaration10.ts, 1, 22)) +} + +export function prepareConfigWithoutAnnotation({ +>prepareConfigWithoutAnnotation : Symbol(prepareConfigWithoutAnnotation, Decl(destructuringParameterDeclaration10.ts, 8, 1)) + + additionalFiles: { +>additionalFiles : Symbol(additionalFiles) + + json = [] +>json : Symbol(json, Decl(destructuringParameterDeclaration10.ts, 11, 22)) + + } = {} +} = {}) { + json +>json : Symbol(json, Decl(destructuringParameterDeclaration10.ts, 11, 22)) +} + +export const prepareConfigWithContextualSignature: (param:{ +>prepareConfigWithContextualSignature : Symbol(prepareConfigWithContextualSignature, Decl(destructuringParameterDeclaration10.ts, 18, 12)) +>param : Symbol(param, Decl(destructuringParameterDeclaration10.ts, 18, 52)) + + additionalFiles?: Partial>; +>additionalFiles : Symbol(additionalFiles, Decl(destructuringParameterDeclaration10.ts, 18, 59)) +>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) + +}) => void = ({ + additionalFiles: { +>additionalFiles : Symbol(additionalFiles, Decl(destructuringParameterDeclaration10.ts, 18, 59)) + + json = [] +>json : Symbol(json, Decl(destructuringParameterDeclaration10.ts, 21, 22)) + + } = {} +} = {}) => { + json // string[] +>json : Symbol(json, Decl(destructuringParameterDeclaration10.ts, 21, 22)) +} + diff --git a/tests/baselines/reference/destructuringParameterDeclaration10(strict=false).types b/tests/baselines/reference/destructuringParameterDeclaration10(strict=false).types new file mode 100644 index 0000000000000..721d45fc041df --- /dev/null +++ b/tests/baselines/reference/destructuringParameterDeclaration10(strict=false).types @@ -0,0 +1,99 @@ +//// [tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration10.ts] //// + +=== destructuringParameterDeclaration10.ts === +export function prepareConfig({ +>prepareConfig : ({ additionalFiles: { json } }?: { additionalFiles?: Partial>; }) => void +> : ^ ^^^ ^^^^^^^^^ + + additionalFiles: { +>additionalFiles : any +> : ^^^ + + json = [] +>json : string[] +> : ^^^^^^^^ +>[] : undefined[] +> : ^^^^^^^^^^^ + + } = {} +>{} : {} +> : ^^ + +}: { + additionalFiles?: Partial>; +>additionalFiles : Partial> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +} = {}) { +>{} : {} +> : ^^ + + json // string[] +>json : string[] +> : ^^^^^^^^ +} + +export function prepareConfigWithoutAnnotation({ +>prepareConfigWithoutAnnotation : ({ additionalFiles: { json } }?: { additionalFiles?: { json?: any[]; }; }) => void +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + additionalFiles: { +>additionalFiles : any +> : ^^^ + + json = [] +>json : any[] +> : ^^^^^ +>[] : undefined[] +> : ^^^^^^^^^^^ + + } = {} +>{} : {} +> : ^^ + +} = {}) { +>{} : {} +> : ^^ + + json +>json : any[] +> : ^^^^^ +} + +export const prepareConfigWithContextualSignature: (param:{ +>prepareConfigWithContextualSignature : (param: { additionalFiles?: Partial>; }) => void +> : ^ ^^ ^^^^^ +>param : { additionalFiles?: Partial>; } +> : ^^^^^^^^^^^^^^^^^^^^ ^^^ + + additionalFiles?: Partial>; +>additionalFiles : Partial> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +}) => void = ({ +>({ additionalFiles: { json = [] } = {}} = {}) => { json // string[]} : ({ additionalFiles: { json } }?: { additionalFiles?: Partial>; }) => void +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^ + + additionalFiles: { +>additionalFiles : any +> : ^^^ + + json = [] +>json : string[] +> : ^^^^^^^^ +>[] : undefined[] +> : ^^^^^^^^^^^ + + } = {} +>{} : {} +> : ^^ + +} = {}) => { +>{} : {} +> : ^^ + + json // string[] +>json : string[] +> : ^^^^^^^^ +} + diff --git a/tests/baselines/reference/destructuringParameterDeclaration10(strict=true).symbols b/tests/baselines/reference/destructuringParameterDeclaration10(strict=true).symbols new file mode 100644 index 0000000000000..a0da095b3f6de --- /dev/null +++ b/tests/baselines/reference/destructuringParameterDeclaration10(strict=true).symbols @@ -0,0 +1,61 @@ +//// [tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration10.ts] //// + +=== destructuringParameterDeclaration10.ts === +export function prepareConfig({ +>prepareConfig : Symbol(prepareConfig, Decl(destructuringParameterDeclaration10.ts, 0, 0)) + + additionalFiles: { +>additionalFiles : Symbol(additionalFiles, Decl(destructuringParameterDeclaration10.ts, 4, 4)) + + json = [] +>json : Symbol(json, Decl(destructuringParameterDeclaration10.ts, 1, 22)) + + } = {} +}: { + additionalFiles?: Partial>; +>additionalFiles : Symbol(additionalFiles, Decl(destructuringParameterDeclaration10.ts, 4, 4)) +>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) + +} = {}) { + json // string[] +>json : Symbol(json, Decl(destructuringParameterDeclaration10.ts, 1, 22)) +} + +export function prepareConfigWithoutAnnotation({ +>prepareConfigWithoutAnnotation : Symbol(prepareConfigWithoutAnnotation, Decl(destructuringParameterDeclaration10.ts, 8, 1)) + + additionalFiles: { +>additionalFiles : Symbol(additionalFiles) + + json = [] +>json : Symbol(json, Decl(destructuringParameterDeclaration10.ts, 11, 22)) + + } = {} +} = {}) { + json +>json : Symbol(json, Decl(destructuringParameterDeclaration10.ts, 11, 22)) +} + +export const prepareConfigWithContextualSignature: (param:{ +>prepareConfigWithContextualSignature : Symbol(prepareConfigWithContextualSignature, Decl(destructuringParameterDeclaration10.ts, 18, 12)) +>param : Symbol(param, Decl(destructuringParameterDeclaration10.ts, 18, 52)) + + additionalFiles?: Partial>; +>additionalFiles : Symbol(additionalFiles, Decl(destructuringParameterDeclaration10.ts, 18, 59)) +>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) + +}) => void = ({ + additionalFiles: { +>additionalFiles : Symbol(additionalFiles, Decl(destructuringParameterDeclaration10.ts, 18, 59)) + + json = [] +>json : Symbol(json, Decl(destructuringParameterDeclaration10.ts, 21, 22)) + + } = {} +} = {}) => { + json // string[] +>json : Symbol(json, Decl(destructuringParameterDeclaration10.ts, 21, 22)) +} + diff --git a/tests/baselines/reference/destructuringParameterDeclaration10(strict=true).types b/tests/baselines/reference/destructuringParameterDeclaration10(strict=true).types new file mode 100644 index 0000000000000..6eabd387b0b59 --- /dev/null +++ b/tests/baselines/reference/destructuringParameterDeclaration10(strict=true).types @@ -0,0 +1,99 @@ +//// [tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration10.ts] //// + +=== destructuringParameterDeclaration10.ts === +export function prepareConfig({ +>prepareConfig : ({ additionalFiles: { json } }?: { additionalFiles?: Partial>; }) => void +> : ^ ^^^ ^^^^^^^^^ + + additionalFiles: { +>additionalFiles : any +> : ^^^ + + json = [] +>json : string[] +> : ^^^^^^^^ +>[] : never[] +> : ^^^^^^^ + + } = {} +>{} : {} +> : ^^ + +}: { + additionalFiles?: Partial>; +>additionalFiles : Partial> | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +} = {}) { +>{} : {} +> : ^^ + + json // string[] +>json : string[] +> : ^^^^^^^^ +} + +export function prepareConfigWithoutAnnotation({ +>prepareConfigWithoutAnnotation : ({ additionalFiles: { json } }?: { additionalFiles?: { json?: never[] | undefined; } | undefined; }) => void +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + additionalFiles: { +>additionalFiles : any +> : ^^^ + + json = [] +>json : never[] +> : ^^^^^^^ +>[] : never[] +> : ^^^^^^^ + + } = {} +>{} : {} +> : ^^ + +} = {}) { +>{} : {} +> : ^^ + + json +>json : never[] +> : ^^^^^^^ +} + +export const prepareConfigWithContextualSignature: (param:{ +>prepareConfigWithContextualSignature : (param: { additionalFiles?: Partial>; }) => void +> : ^ ^^ ^^^^^ +>param : { additionalFiles?: Partial>; } +> : ^^^^^^^^^^^^^^^^^^^^ ^^^ + + additionalFiles?: Partial>; +>additionalFiles : Partial> | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +}) => void = ({ +>({ additionalFiles: { json = [] } = {}} = {}) => { json // string[]} : ({ additionalFiles: { json } }?: { additionalFiles?: Partial>; }) => void +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^ + + additionalFiles: { +>additionalFiles : any +> : ^^^ + + json = [] +>json : string[] +> : ^^^^^^^^ +>[] : never[] +> : ^^^^^^^ + + } = {} +>{} : {} +> : ^^ + +} = {}) => { +>{} : {} +> : ^^ + + json // string[] +>json : string[] +> : ^^^^^^^^ +} + diff --git a/tests/baselines/reference/destructuringParameterDeclaration9(strict=false).symbols b/tests/baselines/reference/destructuringParameterDeclaration9(strict=false).symbols new file mode 100644 index 0000000000000..da7a5cc68b4bb --- /dev/null +++ b/tests/baselines/reference/destructuringParameterDeclaration9(strict=false).symbols @@ -0,0 +1,74 @@ +//// [tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration9.ts] //// + +=== index.js === +/** + * @param {Object} [config] + * @param {Partial>} [config.additionalFiles] + */ +export function prepareConfig({ +>prepareConfig : Symbol(prepareConfig, Decl(index.js, 0, 0)) + + additionalFiles: { +>additionalFiles : Symbol(additionalFiles, Decl(index.js, 2, 3)) + + json = [] +>json : Symbol(json, Decl(index.js, 5, 22)) + + } = {} +} = {}) { + json // string[] +>json : Symbol(json, Decl(index.js, 5, 22)) +} + +export function prepareConfigWithoutAnnotation({ +>prepareConfigWithoutAnnotation : Symbol(prepareConfigWithoutAnnotation, Decl(index.js, 10, 1)) + + additionalFiles: { +>additionalFiles : Symbol(additionalFiles) + + json = [] +>json : Symbol(json, Decl(index.js, 13, 22)) + + } = {} +} = {}) { + json +>json : Symbol(json, Decl(index.js, 13, 22)) +} + +/** @type {(param: { + additionalFiles?: Partial>; +}) => void} */ +export const prepareConfigWithContextualSignature = ({ +>prepareConfigWithContextualSignature : Symbol(prepareConfigWithContextualSignature, Decl(index.js, 23, 12)) + + additionalFiles: { +>additionalFiles : Symbol(additionalFiles, Decl(index.js, 20, 20)) + + json = [] +>json : Symbol(json, Decl(index.js, 24, 22)) + + } = {} +} = {})=> { + json // string[] +>json : Symbol(json, Decl(index.js, 24, 22)) +} + +// Additional repros from https://github.com/microsoft/TypeScript/issues/59936 + +/** + * @param {{ a?: { json?: string[] }}} [config] + */ +function f1({ a: { json = [] } = {} } = {}) { return json } +>f1 : Symbol(f1, Decl(index.js, 29, 1)) +>a : Symbol(a, Decl(index.js, 34, 12)) +>json : Symbol(json, Decl(index.js, 36, 18)) +>json : Symbol(json, Decl(index.js, 36, 18)) + +/** + * @param {[[string[]?]?]} [x] + */ +function f2([[json = []] = []] = []) { return json } +>f2 : Symbol(f2, Decl(index.js, 36, 59)) +>json : Symbol(json, Decl(index.js, 41, 14)) +>json : Symbol(json, Decl(index.js, 41, 14)) + diff --git a/tests/baselines/reference/destructuringParameterDeclaration9(strict=false).types b/tests/baselines/reference/destructuringParameterDeclaration9(strict=false).types new file mode 100644 index 0000000000000..e827977063d76 --- /dev/null +++ b/tests/baselines/reference/destructuringParameterDeclaration9(strict=false).types @@ -0,0 +1,131 @@ +//// [tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration9.ts] //// + +=== index.js === +/** + * @param {Object} [config] + * @param {Partial>} [config.additionalFiles] + */ +export function prepareConfig({ +>prepareConfig : ({ additionalFiles: { json } }?: { additionalFiles?: Partial>;}) => void +> : ^ ^^^ ^^^ ^ ^^^^^^^^^ + + additionalFiles: { +>additionalFiles : any +> : ^^^ + + json = [] +>json : string[] +> : ^^^^^^^^ +>[] : undefined[] +> : ^^^^^^^^^^^ + + } = {} +>{} : {} +> : ^^ + +} = {}) { +>{} : {} +> : ^^ + + json // string[] +>json : string[] +> : ^^^^^^^^ +} + +export function prepareConfigWithoutAnnotation({ +>prepareConfigWithoutAnnotation : ({ additionalFiles: { json } }?: { additionalFiles?: { json?: any[]; }; }) => void +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + additionalFiles: { +>additionalFiles : any +> : ^^^ + + json = [] +>json : any[] +> : ^^^^^ +>[] : undefined[] +> : ^^^^^^^^^^^ + + } = {} +>{} : {} +> : ^^ + +} = {}) { +>{} : {} +> : ^^ + + json +>json : any[] +> : ^^^^^ +} + +/** @type {(param: { + additionalFiles?: Partial>; +}) => void} */ +export const prepareConfigWithContextualSignature = ({ +>prepareConfigWithContextualSignature : (param: { additionalFiles?: Partial>; }) => void +> : ^ ^^ ^^^^^ +>({ additionalFiles: { json = [] } = {}} = {})=> { json // string[]} : ({ additionalFiles: { json } }?: { additionalFiles?: Partial>; }) => void +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^ + + additionalFiles: { +>additionalFiles : any +> : ^^^ + + json = [] +>json : string[] +> : ^^^^^^^^ +>[] : undefined[] +> : ^^^^^^^^^^^ + + } = {} +>{} : {} +> : ^^ + +} = {})=> { +>{} : {} +> : ^^ + + json // string[] +>json : string[] +> : ^^^^^^^^ +} + +// Additional repros from https://github.com/microsoft/TypeScript/issues/59936 + +/** + * @param {{ a?: { json?: string[] }}} [config] + */ +function f1({ a: { json = [] } = {} } = {}) { return json } +>f1 : ({ a: { json } }?: { a?: { json?: string[]; }; }) => string[] +> : ^ ^^^ ^^^^^^^^^^^^^ +>a : any +> : ^^^ +>json : string[] +> : ^^^^^^^^ +>[] : undefined[] +> : ^^^^^^^^^^^ +>{} : {} +> : ^^ +>{} : {} +> : ^^ +>json : string[] +> : ^^^^^^^^ + +/** + * @param {[[string[]?]?]} [x] + */ +function f2([[json = []] = []] = []) { return json } +>f2 : ([[json]]?: [[string[]?]?]) => string[] +> : ^ ^^^ ^^^^^^^^^^^^^ +>json : string[] +> : ^^^^^^^^ +>[] : undefined[] +> : ^^^^^^^^^^^ +>[] : [] +> : ^^ +>[] : [] +> : ^^ +>json : string[] +> : ^^^^^^^^ + diff --git a/tests/baselines/reference/destructuringParameterDeclaration9(strict=true).errors.txt b/tests/baselines/reference/destructuringParameterDeclaration9(strict=true).errors.txt new file mode 100644 index 0000000000000..6f0315e55926d --- /dev/null +++ b/tests/baselines/reference/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/tests/baselines/reference/destructuringParameterDeclaration9(strict=true).symbols b/tests/baselines/reference/destructuringParameterDeclaration9(strict=true).symbols new file mode 100644 index 0000000000000..648e03984cab4 --- /dev/null +++ b/tests/baselines/reference/destructuringParameterDeclaration9(strict=true).symbols @@ -0,0 +1,71 @@ +//// [tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration9.ts] //// + +=== index.js === +/** + * @param {Object} [config] + * @param {Partial>} [config.additionalFiles] + */ +export function prepareConfig({ +>prepareConfig : Symbol(prepareConfig, Decl(index.js, 0, 0)) + + additionalFiles: { + json = [] +>json : Symbol(json, Decl(index.js, 5, 22)) + + } = {} +} = {}) { + json // string[] +>json : Symbol(json, Decl(index.js, 5, 22)) +} + +export function prepareConfigWithoutAnnotation({ +>prepareConfigWithoutAnnotation : Symbol(prepareConfigWithoutAnnotation, Decl(index.js, 10, 1)) + + additionalFiles: { +>additionalFiles : Symbol(additionalFiles) + + json = [] +>json : Symbol(json, Decl(index.js, 13, 22)) + + } = {} +} = {}) { + json +>json : Symbol(json, Decl(index.js, 13, 22)) +} + +/** @type {(param: { + additionalFiles?: Partial>; +}) => void} */ +export const prepareConfigWithContextualSignature = ({ +>prepareConfigWithContextualSignature : Symbol(prepareConfigWithContextualSignature, Decl(index.js, 23, 12)) + + additionalFiles: { +>additionalFiles : Symbol(additionalFiles, Decl(index.js, 20, 20)) + + json = [] +>json : Symbol(json, Decl(index.js, 24, 22)) + + } = {} +} = {})=> { + json // string[] +>json : Symbol(json, Decl(index.js, 24, 22)) +} + +// Additional repros from https://github.com/microsoft/TypeScript/issues/59936 + +/** + * @param {{ a?: { json?: string[] }}} [config] + */ +function f1({ a: { json = [] } = {} } = {}) { return json } +>f1 : Symbol(f1, Decl(index.js, 29, 1)) +>json : Symbol(json, Decl(index.js, 36, 18)) +>json : Symbol(json, Decl(index.js, 36, 18)) + +/** + * @param {[[string[]?]?]} [x] + */ +function f2([[json = []] = []] = []) { return json } +>f2 : Symbol(f2, Decl(index.js, 36, 59)) +>json : Symbol(json, Decl(index.js, 41, 14)) +>json : Symbol(json, Decl(index.js, 41, 14)) + diff --git a/tests/baselines/reference/destructuringParameterDeclaration9(strict=true).types b/tests/baselines/reference/destructuringParameterDeclaration9(strict=true).types new file mode 100644 index 0000000000000..e95d65bd2dff4 --- /dev/null +++ b/tests/baselines/reference/destructuringParameterDeclaration9(strict=true).types @@ -0,0 +1,131 @@ +//// [tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration9.ts] //// + +=== index.js === +/** + * @param {Object} [config] + * @param {Partial>} [config.additionalFiles] + */ +export function prepareConfig({ +>prepareConfig : ({ additionalFiles: { json } }?: { additionalFiles?: Partial> | undefined;}) => void +> : ^ ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^ + + additionalFiles: { +>additionalFiles : any +> : ^^^ + + json = [] +>json : string[] +> : ^^^^^^^^ +>[] : never[] +> : ^^^^^^^ + + } = {} +>{} : {} +> : ^^ + +} = {}) { +>{} : {} +> : ^^ + + json // string[] +>json : string[] +> : ^^^^^^^^ +} + +export function prepareConfigWithoutAnnotation({ +>prepareConfigWithoutAnnotation : ({ additionalFiles: { json } }?: { additionalFiles?: { json?: never[] | undefined; } | undefined; }) => void +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + additionalFiles: { +>additionalFiles : any +> : ^^^ + + json = [] +>json : any[] +> : ^^^^^ +>[] : never[] +> : ^^^^^^^ + + } = {} +>{} : {} +> : ^^ + +} = {}) { +>{} : {} +> : ^^ + + json +>json : any[] +> : ^^^^^ +} + +/** @type {(param: { + additionalFiles?: Partial>; +}) => void} */ +export const prepareConfigWithContextualSignature = ({ +>prepareConfigWithContextualSignature : (param: { additionalFiles?: Partial>; }) => void +> : ^ ^^ ^^^^^ +>({ additionalFiles: { json = [] } = {}} = {})=> { json // string[]} : ({ additionalFiles: { json } }?: { additionalFiles?: Partial>; }) => void +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^ + + additionalFiles: { +>additionalFiles : any +> : ^^^ + + json = [] +>json : string[] +> : ^^^^^^^^ +>[] : never[] +> : ^^^^^^^ + + } = {} +>{} : {} +> : ^^ + +} = {})=> { +>{} : {} +> : ^^ + + json // string[] +>json : string[] +> : ^^^^^^^^ +} + +// Additional repros from https://github.com/microsoft/TypeScript/issues/59936 + +/** + * @param {{ a?: { json?: string[] }}} [config] + */ +function f1({ a: { json = [] } = {} } = {}) { return json } +>f1 : ({ a: { json } }?: { a?: { json?: string[]; }; }) => string[] +> : ^ ^^^ ^^^^^^^^^^^^^ +>a : any +> : ^^^ +>json : string[] +> : ^^^^^^^^ +>[] : never[] +> : ^^^^^^^ +>{} : {} +> : ^^ +>{} : {} +> : ^^ +>json : string[] +> : ^^^^^^^^ + +/** + * @param {[[string[]?]?]} [x] + */ +function f2([[json = []] = []] = []) { return json } +>f2 : ([[json]]?: [[string[]?]?]) => string[] +> : ^ ^^^ ^^^^^^^^^^^^^ +>json : string[] +> : ^^^^^^^^ +>[] : never[] +> : ^^^^^^^ +>[] : [] +> : ^^ +>[] : [] +> : ^^ +>json : string[] +> : ^^^^^^^^ + From 1c25b1a91ad1d4070238684dbad0d330ddd865e0 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Fri, 27 Sep 2024 11:50:57 -0700 Subject: [PATCH 4/4] Fix formatting --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0ed70c4df4e03..2461d6a856b40 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -40770,7 +40770,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function widenTypeInferredFromInitializer(declaration: HasExpressionInitializer, type: Type) { - const widened = getWidenedLiteralTypeForInitializer(declaration, type) + const widened = getWidenedLiteralTypeForInitializer(declaration, type); if (isInJSFile(declaration)) { if (isEmptyLiteralType(widened)) { reportImplicitAny(declaration, anyType);