From 09da3d0bcd21676f2290e51181b3ceafee8ae5ce Mon Sep 17 00:00:00 2001 From: Oleksandr Tarasiuk Date: Tue, 27 Oct 2026 12:06:41 +0200 Subject: [PATCH 1/2] fix(64974): fix contextual typing for destructured parameter defaults --- tsc/internal/checker/checker.go | 5 +- ...ngPatternDefaultMissingElements.errors.txt | 95 ++++++++- ...ndingPatternDefaultMissingElements.symbols | 156 ++++++++++++++ ...BindingPatternDefaultMissingElements.types | 201 ++++++++++++++++++ ...ectBindingPatternDefaultMissingElements.ts | 47 ++++ 5 files changed, 501 insertions(+), 3 deletions(-) diff --git a/tsc/internal/checker/checker.go b/tsc/internal/checker/checker.go index 67a9ab08cfd17..eaa1bde6db78b 100644 --- a/tsc/internal/checker/checker.go +++ b/tsc/internal/checker/checker.go @@ -17219,11 +17219,12 @@ func (c *Checker) checkDeclarationInitializer(declaration *ast.Node, checkMode C t = c.checkExpressionCachedEx(initializer, checkMode) } } - if ast.IsParameterDeclaration(ast.GetRootDeclaration(declaration)) { + root := ast.GetRootDeclaration(declaration) + if ast.IsParameterDeclaration(root) { name := declaration.Name() switch name.Kind { case ast.KindObjectBindingPattern: - if isObjectLiteralType(t) { + if isObjectLiteralType(t) && c.getContextualTypeForVariableLikeDeclaration(root, ContextFlagsNone) == nil { return c.padObjectLiteralType(t, name) } case ast.KindArrayBindingPattern: diff --git a/tsc/testdata/baselines/reference/compiler/objectBindingPatternDefaultMissingElements.errors.txt b/tsc/testdata/baselines/reference/compiler/objectBindingPatternDefaultMissingElements.errors.txt index 823bd410ef0cb..b041ac978c291 100644 --- a/tsc/testdata/baselines/reference/compiler/objectBindingPatternDefaultMissingElements.errors.txt +++ b/tsc/testdata/baselines/reference/compiler/objectBindingPatternDefaultMissingElements.errors.txt @@ -3,6 +3,24 @@ /main.ts(5,5): error TS7031: Binding element 'required' implicitly has an 'any' type. /main.ts(10,5): error TS7031: Binding element 'required' implicitly has an 'any' type. /main.ts(15,5): error TS7031: Binding element 'required' implicitly has an 'any' type. +/main.ts(35,11): error TS2322: Type 'string | undefined' is not assignable to type 'number'. + Type 'undefined' is not assignable to type 'number'. +/main.ts(36,11): error TS2322: Type 'number | undefined' is not assignable to type 'string'. + Type 'undefined' is not assignable to type 'string'. +/main.ts(41,11): error TS2322: Type 'number | undefined' is not assignable to type 'string'. + Type 'undefined' is not assignable to type 'string'. +/main.ts(46,11): error TS2322: Type 'number | undefined' is not assignable to type 'string'. + Type 'undefined' is not assignable to type 'string'. +/main.ts(50,59): error TS2339: Property 'b' does not exist on type '{ a?: number | undefined; }'. +/main.ts(51,11): error TS2322: Type 'number | undefined' is not assignable to type 'string'. + Type 'undefined' is not assignable to type 'string'. +/main.ts(55,11): error TS2322: Type 'number | undefined' is not assignable to type 'string'. + Type 'undefined' is not assignable to type 'string'. +/main.ts(59,11): error TS2322: Type 'number' is not assignable to type 'string'. +/main.ts(68,11): error TS2322: Type 'number | undefined' is not assignable to type 'string'. + Type 'undefined' is not assignable to type 'string'. +/main.ts(72,11): error TS2322: Type 'number | undefined' is not assignable to type 'string'. + Type 'undefined' is not assignable to type 'string'. ==== /unchecked.js (0 errors) ==== @@ -32,7 +50,7 @@ optional = false, ] = []) => {}; -==== /main.ts (3 errors) ==== +==== /main.ts (13 errors) ==== import { checkedArray, checkedObject } from "./checked"; import { uncheckedArray, uncheckedObject } from "./unchecked"; @@ -65,4 +83,79 @@ checkedArray(["value"]); typedObject({ required: "value" }); typedArray(["value"]); + + type F = (input?: { a?: string; b?: number }) => number; + export const f1: F = ({ a, b } = {}) => (a ? 1 : 0) + (b ?? 0); + + export const f2: (input: { a?: string; b?: number }) => number = ({ a, b } = {}) => (a ? 1 : 0) + (b ?? 0); + + declare function f3(callback: F): void; + f3(({ a, b } = {}) => { + const c: number = a; + ~ +!!! error TS2322: Type 'string | undefined' is not assignable to type 'number'. +!!! error TS2322: Type 'undefined' is not assignable to type 'number'. + const d: string = b; + ~ +!!! error TS2322: Type 'number | undefined' is not assignable to type 'string'. +!!! error TS2322: Type 'undefined' is not assignable to type 'string'. + return 0; + }); + + export const f4: (input?: { a?: { b?: number } }) => number = ({ a: { b } = {} } = {}) => { + const c: string = b; + ~ +!!! error TS2322: Type 'number | undefined' is not assignable to type 'string'. +!!! error TS2322: Type 'undefined' is not assignable to type 'string'. + return b ?? 0; + }; + + export function f5({ a: { b } = {} }: { a?: { b?: number } }) { + const c: string = b; + ~ +!!! error TS2322: Type 'number | undefined' is not assignable to type 'string'. +!!! error TS2322: Type 'undefined' is not assignable to type 'string'. + return b; + } + + export const f6: (input?: { a?: number }) => void = ({ a, b } = {}) => { + ~ +!!! error TS2339: Property 'b' does not exist on type '{ a?: number | undefined; }'. + const c: string = a; + ~ +!!! error TS2322: Type 'number | undefined' is not assignable to type 'string'. +!!! error TS2322: Type 'undefined' is not assignable to type 'string'. + }; + + export const f7: (input?: [{ a?: number }?]) => void = ([{ a } = {}] = []) => { + const b: string = a; + ~ +!!! error TS2322: Type 'number | undefined' is not assignable to type 'string'. +!!! error TS2322: Type 'undefined' is not assignable to type 'string'. + }; + + export const f8: (input?: { [key: string]: number }) => void = ({ a } = {}) => { + const b: string = a; + ~ +!!! error TS2322: Type 'number' is not assignable to type 'string'. + }; + + export const f9: (input?: any) => void = ({ a: { b } = {} } = {}) => { + b; + }; + + declare function f10(value: T, callback: (input?: Partial) => void): void; + f10({ a: 1 }, ({ a } = {}) => { + const b: string = a; + ~ +!!! error TS2322: Type 'number | undefined' is not assignable to type 'string'. +!!! error TS2322: Type 'undefined' is not assignable to type 'string'. + }); + + export const f11: (input?: { a?: number }[]) => void = ([...[{ a } = {}]] = []) => { + const b: string = a; + ~ +!!! error TS2322: Type 'number | undefined' is not assignable to type 'string'. +!!! error TS2322: Type 'undefined' is not assignable to type 'string'. + }; \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/compiler/objectBindingPatternDefaultMissingElements.symbols b/tsc/testdata/baselines/reference/compiler/objectBindingPatternDefaultMissingElements.symbols index 5542ea8d095bf..e088f2174ec64 100644 --- a/tsc/testdata/baselines/reference/compiler/objectBindingPatternDefaultMissingElements.symbols +++ b/tsc/testdata/baselines/reference/compiler/objectBindingPatternDefaultMissingElements.symbols @@ -114,3 +114,159 @@ typedObject({ required: "value" }); typedArray(["value"]); >typedArray : Symbol(typedArray, Decl(main.ts, 8, 12)) +type F = (input?: { a?: string; b?: number }) => number; +>F : Symbol(F, Decl(main.ts, 25, 22)) +>input : Symbol(input, Decl(main.ts, 27, 10)) +>a : Symbol(a, Decl(main.ts, 27, 19)) +>b : Symbol(b, Decl(main.ts, 27, 31)) + +export const f1: F = ({ a, b } = {}) => (a ? 1 : 0) + (b ?? 0); +>f1 : Symbol(f1, Decl(main.ts, 28, 12)) +>F : Symbol(F, Decl(main.ts, 25, 22)) +>a : Symbol(a, Decl(main.ts, 28, 23)) +>b : Symbol(b, Decl(main.ts, 28, 26)) +>a : Symbol(a, Decl(main.ts, 28, 23)) +>b : Symbol(b, Decl(main.ts, 28, 26)) + +export const f2: (input: { a?: string; b?: number }) => number = ({ a, b } = {}) => (a ? 1 : 0) + (b ?? 0); +>f2 : Symbol(f2, Decl(main.ts, 30, 12)) +>input : Symbol(input, Decl(main.ts, 30, 18)) +>a : Symbol(a, Decl(main.ts, 30, 26)) +>b : Symbol(b, Decl(main.ts, 30, 38)) +>a : Symbol(a, Decl(main.ts, 30, 67)) +>b : Symbol(b, Decl(main.ts, 30, 70)) +>a : Symbol(a, Decl(main.ts, 30, 67)) +>b : Symbol(b, Decl(main.ts, 30, 70)) + +declare function f3(callback: F): void; +>f3 : Symbol(f3, Decl(main.ts, 30, 107)) +>callback : Symbol(callback, Decl(main.ts, 32, 20)) +>F : Symbol(F, Decl(main.ts, 25, 22)) + +f3(({ a, b } = {}) => { +>f3 : Symbol(f3, Decl(main.ts, 30, 107)) +>a : Symbol(a, Decl(main.ts, 33, 5)) +>b : Symbol(b, Decl(main.ts, 33, 8)) + + const c: number = a; +>c : Symbol(c, Decl(main.ts, 34, 9)) +>a : Symbol(a, Decl(main.ts, 33, 5)) + + const d: string = b; +>d : Symbol(d, Decl(main.ts, 35, 9)) +>b : Symbol(b, Decl(main.ts, 33, 8)) + + return 0; +}); + +export const f4: (input?: { a?: { b?: number } }) => number = ({ a: { b } = {} } = {}) => { +>f4 : Symbol(f4, Decl(main.ts, 39, 12)) +>input : Symbol(input, Decl(main.ts, 39, 18)) +>a : Symbol(a, Decl(main.ts, 39, 27)) +>b : Symbol(b, Decl(main.ts, 39, 33)) +>b : Symbol(b, Decl(main.ts, 39, 69)) + + const c: string = b; +>c : Symbol(c, Decl(main.ts, 40, 9)) +>b : Symbol(b, Decl(main.ts, 39, 69)) + + return b ?? 0; +>b : Symbol(b, Decl(main.ts, 39, 69)) + +}; + +export function f5({ a: { b } = {} }: { a?: { b?: number } }) { +>f5 : Symbol(f5, Decl(main.ts, 42, 2)) +>a : Symbol(a, Decl(main.ts, 44, 39)) +>b : Symbol(b, Decl(main.ts, 44, 25)) +>a : Symbol(a, Decl(main.ts, 44, 39)) +>b : Symbol(b, Decl(main.ts, 44, 45)) + + const c: string = b; +>c : Symbol(c, Decl(main.ts, 45, 9)) +>b : Symbol(b, Decl(main.ts, 44, 25)) + + return b; +>b : Symbol(b, Decl(main.ts, 44, 25)) +} + +export const f6: (input?: { a?: number }) => void = ({ a, b } = {}) => { +>f6 : Symbol(f6, Decl(main.ts, 49, 12)) +>input : Symbol(input, Decl(main.ts, 49, 18)) +>a : Symbol(a, Decl(main.ts, 49, 27)) +>a : Symbol(a, Decl(main.ts, 49, 54)) +>b : Symbol(b, Decl(main.ts, 49, 57)) + + const c: string = a; +>c : Symbol(c, Decl(main.ts, 50, 9)) +>a : Symbol(a, Decl(main.ts, 49, 54)) + +}; + +export const f7: (input?: [{ a?: number }?]) => void = ([{ a } = {}] = []) => { +>f7 : Symbol(f7, Decl(main.ts, 53, 12)) +>input : Symbol(input, Decl(main.ts, 53, 18)) +>a : Symbol(a, Decl(main.ts, 53, 28)) +>a : Symbol(a, Decl(main.ts, 53, 58)) + + const b: string = a; +>b : Symbol(b, Decl(main.ts, 54, 9)) +>a : Symbol(a, Decl(main.ts, 53, 58)) + +}; + +export const f8: (input?: { [key: string]: number }) => void = ({ a } = {}) => { +>f8 : Symbol(f8, Decl(main.ts, 57, 12)) +>input : Symbol(input, Decl(main.ts, 57, 18)) +>key : Symbol(key, Decl(main.ts, 57, 29)) +>a : Symbol(a, Decl(main.ts, 57, 65)) + + const b: string = a; +>b : Symbol(b, Decl(main.ts, 58, 9)) +>a : Symbol(a, Decl(main.ts, 57, 65)) + +}; + +export const f9: (input?: any) => void = ({ a: { b } = {} } = {}) => { +>f9 : Symbol(f9, Decl(main.ts, 61, 12)) +>input : Symbol(input, Decl(main.ts, 61, 18)) +>b : Symbol(b, Decl(main.ts, 61, 48)) + + b; +>b : Symbol(b, Decl(main.ts, 61, 48)) + +}; + +declare function f10(value: T, callback: (input?: Partial) => void): void; +>f10 : Symbol(f10, Decl(main.ts, 63, 2)) +>T : Symbol(T, Decl(main.ts, 65, 21)) +>value : Symbol(value, Decl(main.ts, 65, 24)) +>T : Symbol(T, Decl(main.ts, 65, 21)) +>callback : Symbol(callback, Decl(main.ts, 65, 33)) +>input : Symbol(input, Decl(main.ts, 65, 45)) +>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(main.ts, 65, 21)) + +f10({ a: 1 }, ({ a } = {}) => { +>f10 : Symbol(f10, Decl(main.ts, 63, 2)) +>a : Symbol(a, Decl(main.ts, 66, 5)) +>a : Symbol(a, Decl(main.ts, 66, 16)) + + const b: string = a; +>b : Symbol(b, Decl(main.ts, 67, 9)) +>a : Symbol(a, Decl(main.ts, 66, 16)) + +}); + +export const f11: (input?: { a?: number }[]) => void = ([...[{ a } = {}]] = []) => { +>f11 : Symbol(f11, Decl(main.ts, 70, 12)) +>input : Symbol(input, Decl(main.ts, 70, 19)) +>a : Symbol(a, Decl(main.ts, 70, 28)) +>a : Symbol(a, Decl(main.ts, 70, 62)) + + const b: string = a; +>b : Symbol(b, Decl(main.ts, 71, 9)) +>a : Symbol(a, Decl(main.ts, 70, 62)) + +}; + diff --git a/tsc/testdata/baselines/reference/compiler/objectBindingPatternDefaultMissingElements.types b/tsc/testdata/baselines/reference/compiler/objectBindingPatternDefaultMissingElements.types index 1791cbfaebf14..0b11169868215 100644 --- a/tsc/testdata/baselines/reference/compiler/objectBindingPatternDefaultMissingElements.types +++ b/tsc/testdata/baselines/reference/compiler/objectBindingPatternDefaultMissingElements.types @@ -153,3 +153,204 @@ typedArray(["value"]); >["value"] : [string] >"value" : "value" +type F = (input?: { a?: string; b?: number }) => number; +>F : F +>input : { a?: string; b?: number; } | undefined +>a : string | undefined +>b : number | undefined + +export const f1: F = ({ a, b } = {}) => (a ? 1 : 0) + (b ?? 0); +>f1 : F +>({ a, b } = {}) => (a ? 1 : 0) + (b ?? 0) : ({ a, b }?: { a?: string; b?: number; } | undefined) => number +>a : string | undefined +>b : number | undefined +>{} : {} +>(a ? 1 : 0) + (b ?? 0) : number +>(a ? 1 : 0) : 0 | 1 +>a ? 1 : 0 : 0 | 1 +>a : string | undefined +>1 : 1 +>0 : 0 +>(b ?? 0) : number +>b ?? 0 : number +>b : number | undefined +>0 : 0 + +export const f2: (input: { a?: string; b?: number }) => number = ({ a, b } = {}) => (a ? 1 : 0) + (b ?? 0); +>f2 : (input: { a?: string; b?: number; }) => number +>input : { a?: string; b?: number; } +>a : string | undefined +>b : number | undefined +>({ a, b } = {}) => (a ? 1 : 0) + (b ?? 0) : ({ a, b }?: { a?: string; b?: number; }) => number +>a : string | undefined +>b : number | undefined +>{} : {} +>(a ? 1 : 0) + (b ?? 0) : number +>(a ? 1 : 0) : 0 | 1 +>a ? 1 : 0 : 0 | 1 +>a : string | undefined +>1 : 1 +>0 : 0 +>(b ?? 0) : number +>b ?? 0 : number +>b : number | undefined +>0 : 0 + +declare function f3(callback: F): void; +>f3 : (callback: F) => void +>callback : F + +f3(({ a, b } = {}) => { +>f3(({ a, b } = {}) => { const c: number = a; const d: string = b; return 0;}) : void +>f3 : (callback: F) => void +>({ a, b } = {}) => { const c: number = a; const d: string = b; return 0;} : ({ a, b }?: { a?: string; b?: number; } | undefined) => number +>a : string | undefined +>b : number | undefined +>{} : {} + + const c: number = a; +>c : number +>a : string | undefined + + const d: string = b; +>d : string +>b : number | undefined + + return 0; +>0 : 0 + +}); + +export const f4: (input?: { a?: { b?: number } }) => number = ({ a: { b } = {} } = {}) => { +>f4 : (input?: { a?: { b?: number; }; }) => number +>input : { a?: { b?: number; }; } | undefined +>a : { b?: number; } | undefined +>b : number | undefined +>({ a: { b } = {} } = {}) => { const c: string = b; return b ?? 0;} : ({ a: { b } }?: { a?: { b?: number; }; } | undefined) => number +>a : any +>b : number | undefined +>{} : {} +>{} : {} + + const c: string = b; +>c : string +>b : number | undefined + + return b ?? 0; +>b ?? 0 : number +>b : number | undefined +>0 : 0 + +}; + +export function f5({ a: { b } = {} }: { a?: { b?: number } }) { +>f5 : ({ a: { b } }: { a?: { b?: number; }; }) => number | undefined +>a : any +>b : number | undefined +>{} : {} +>a : { b?: number; } | undefined +>b : number | undefined + + const c: string = b; +>c : string +>b : number | undefined + + return b; +>b : number | undefined +} + +export const f6: (input?: { a?: number }) => void = ({ a, b } = {}) => { +>f6 : (input?: { a?: number; }) => void +>input : { a?: number; } | undefined +>a : number | undefined +>({ a, b } = {}) => { const c: string = a;} : ({ a, b }?: { a?: number; } | undefined) => void +>a : number | undefined +>b : any +>{} : {} + + const c: string = a; +>c : string +>a : number | undefined + +}; + +export const f7: (input?: [{ a?: number }?]) => void = ([{ a } = {}] = []) => { +>f7 : (input?: [{ a?: number; }?]) => void +>input : [({ a?: number; } | undefined)?] | undefined +>a : number | undefined +>([{ a } = {}] = []) => { const b: string = a;} : ([{ a }]?: [({ a?: number; } | undefined)?] | undefined) => void +>a : number | undefined +>{} : {} +>[] : [] + + const b: string = a; +>b : string +>a : number | undefined + +}; + +export const f8: (input?: { [key: string]: number }) => void = ({ a } = {}) => { +>f8 : (input?: { [key: string]: number; }) => void +>input : { [key: string]: number; } | undefined +>key : string +>({ a } = {}) => { const b: string = a;} : ({ a }?: { [key: string]: number; } | undefined) => void +>a : number +>{} : {} + + const b: string = a; +>b : string +>a : number + +}; + +export const f9: (input?: any) => void = ({ a: { b } = {} } = {}) => { +>f9 : (input?: any) => void +>input : any +>({ a: { b } = {} } = {}) => { b;} : ({ a: { b } }?: any) => void +>a : any +>b : any +>{} : {} +>{} : {} + + b; +>b : any + +}; + +declare function f10(value: T, callback: (input?: Partial) => void): void; +>f10 : (value: T, callback: (input?: Partial) => void) => void +>value : T +>callback : (input?: Partial) => void +>input : Partial | undefined + +f10({ a: 1 }, ({ a } = {}) => { +>f10({ a: 1 }, ({ a } = {}) => { const b: string = a;}) : void +>f10 : (value: T, callback: (input?: Partial) => void) => void +>{ a: 1 } : { a: number; } +>a : number +>1 : 1 +>({ a } = {}) => { const b: string = a;} : ({ a }?: Partial<{ a: number; }> | undefined) => void +>a : number | undefined +>{} : {} + + const b: string = a; +>b : string +>a : number | undefined + +}); + +export const f11: (input?: { a?: number }[]) => void = ([...[{ a } = {}]] = []) => { +>f11 : (input?: { a?: number; }[]) => void +>input : { a?: number; }[] | undefined +>a : number | undefined +>([...[{ a } = {}]] = []) => { const b: string = a;} : ([...[{ a }]]?: { a?: number; }[] | undefined) => void +>a : number | undefined +>{} : {} +>[] : never[] + + const b: string = a; +>b : string +>a : number | undefined + +}; + diff --git a/tsc/testdata/tests/cases/compiler/objectBindingPatternDefaultMissingElements.ts b/tsc/testdata/tests/cases/compiler/objectBindingPatternDefaultMissingElements.ts index e0ea93281bfc9..cc1004369b766 100644 --- a/tsc/testdata/tests/cases/compiler/objectBindingPatternDefaultMissingElements.ts +++ b/tsc/testdata/tests/cases/compiler/objectBindingPatternDefaultMissingElements.ts @@ -53,3 +53,50 @@ checkedObject({ required: "value" }); checkedArray(["value"]); typedObject({ required: "value" }); typedArray(["value"]); + +type F = (input?: { a?: string; b?: number }) => number; +export const f1: F = ({ a, b } = {}) => (a ? 1 : 0) + (b ?? 0); + +export const f2: (input: { a?: string; b?: number }) => number = ({ a, b } = {}) => (a ? 1 : 0) + (b ?? 0); + +declare function f3(callback: F): void; +f3(({ a, b } = {}) => { + const c: number = a; + const d: string = b; + return 0; +}); + +export const f4: (input?: { a?: { b?: number } }) => number = ({ a: { b } = {} } = {}) => { + const c: string = b; + return b ?? 0; +}; + +export function f5({ a: { b } = {} }: { a?: { b?: number } }) { + const c: string = b; + return b; +} + +export const f6: (input?: { a?: number }) => void = ({ a, b } = {}) => { + const c: string = a; +}; + +export const f7: (input?: [{ a?: number }?]) => void = ([{ a } = {}] = []) => { + const b: string = a; +}; + +export const f8: (input?: { [key: string]: number }) => void = ({ a } = {}) => { + const b: string = a; +}; + +export const f9: (input?: any) => void = ({ a: { b } = {} } = {}) => { + b; +}; + +declare function f10(value: T, callback: (input?: Partial) => void): void; +f10({ a: 1 }, ({ a } = {}) => { + const b: string = a; +}); + +export const f11: (input?: { a?: number }[]) => void = ([...[{ a } = {}]] = []) => { + const b: string = a; +}; From 667c4f22010895da2907e930ee6ecbdcbb50fa36 Mon Sep 17 00:00:00 2001 From: Oleksandr Tarasiuk Date: Tue, 27 Oct 2026 21:22:41 +0200 Subject: [PATCH 2/2] add additional tests --- ...ngPatternDefaultMissingElements.errors.txt | 4 +++ ...ndingPatternDefaultMissingElements.symbols | 24 ++++++++++++++ ...BindingPatternDefaultMissingElements.types | 33 +++++++++++++++++++ ...ectBindingPatternDefaultMissingElements.ts | 4 +++ 4 files changed, 65 insertions(+) diff --git a/tsc/testdata/baselines/reference/compiler/objectBindingPatternDefaultMissingElements.errors.txt b/tsc/testdata/baselines/reference/compiler/objectBindingPatternDefaultMissingElements.errors.txt index b041ac978c291..8b17a30ccfe0a 100644 --- a/tsc/testdata/baselines/reference/compiler/objectBindingPatternDefaultMissingElements.errors.txt +++ b/tsc/testdata/baselines/reference/compiler/objectBindingPatternDefaultMissingElements.errors.txt @@ -158,4 +158,8 @@ !!! error TS2322: Type 'number | undefined' is not assignable to type 'string'. !!! error TS2322: Type 'undefined' is not assignable to type 'string'. }; + + export const f12: (input: { a: boolean; b?: string }) => string = ({ a, b } = { a: false }) => `${a}${b}`; + + export const f13 = (input: { a?: number; b?: string }[]) => input.map(({ a, b } = {}) => `${a}${b}`); \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/compiler/objectBindingPatternDefaultMissingElements.symbols b/tsc/testdata/baselines/reference/compiler/objectBindingPatternDefaultMissingElements.symbols index e088f2174ec64..6e3cf3d45c050 100644 --- a/tsc/testdata/baselines/reference/compiler/objectBindingPatternDefaultMissingElements.symbols +++ b/tsc/testdata/baselines/reference/compiler/objectBindingPatternDefaultMissingElements.symbols @@ -270,3 +270,27 @@ export const f11: (input?: { a?: number }[]) => void = ([...[{ a } = {}]] = []) }; +export const f12: (input: { a: boolean; b?: string }) => string = ({ a, b } = { a: false }) => `${a}${b}`; +>f12 : Symbol(f12, Decl(main.ts, 74, 12)) +>input : Symbol(input, Decl(main.ts, 74, 19)) +>a : Symbol(a, Decl(main.ts, 74, 27)) +>b : Symbol(b, Decl(main.ts, 74, 39)) +>a : Symbol(a, Decl(main.ts, 74, 68)) +>b : Symbol(b, Decl(main.ts, 74, 71)) +>a : Symbol(a, Decl(main.ts, 74, 79)) +>a : Symbol(a, Decl(main.ts, 74, 68)) +>b : Symbol(b, Decl(main.ts, 74, 71)) + +export const f13 = (input: { a?: number; b?: string }[]) => input.map(({ a, b } = {}) => `${a}${b}`); +>f13 : Symbol(f13, Decl(main.ts, 76, 12)) +>input : Symbol(input, Decl(main.ts, 76, 20)) +>a : Symbol(a, Decl(main.ts, 76, 28)) +>b : Symbol(b, Decl(main.ts, 76, 40)) +>input.map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --)) +>input : Symbol(input, Decl(main.ts, 76, 20)) +>map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --)) +>a : Symbol(a, Decl(main.ts, 76, 72)) +>b : Symbol(b, Decl(main.ts, 76, 75)) +>a : Symbol(a, Decl(main.ts, 76, 72)) +>b : Symbol(b, Decl(main.ts, 76, 75)) + diff --git a/tsc/testdata/baselines/reference/compiler/objectBindingPatternDefaultMissingElements.types b/tsc/testdata/baselines/reference/compiler/objectBindingPatternDefaultMissingElements.types index 0b11169868215..223d002095b2f 100644 --- a/tsc/testdata/baselines/reference/compiler/objectBindingPatternDefaultMissingElements.types +++ b/tsc/testdata/baselines/reference/compiler/objectBindingPatternDefaultMissingElements.types @@ -354,3 +354,36 @@ export const f11: (input?: { a?: number }[]) => void = ([...[{ a } = {}]] = []) }; +export const f12: (input: { a: boolean; b?: string }) => string = ({ a, b } = { a: false }) => `${a}${b}`; +>f12 : (input: { a: boolean; b?: string; }) => string +>input : { a: boolean; b?: string; } +>a : boolean +>b : string | undefined +>({ a, b } = { a: false }) => `${a}${b}` : ({ a, b }?: { a: boolean; b?: string; }) => string +>a : boolean +>b : string | undefined +>{ a: false } : { a: false; } +>a : false +>false : false +>`${a}${b}` : string +>a : boolean +>b : string | undefined + +export const f13 = (input: { a?: number; b?: string }[]) => input.map(({ a, b } = {}) => `${a}${b}`); +>f13 : (input: { a?: number; b?: string; }[]) => string[] +>(input: { a?: number; b?: string }[]) => input.map(({ a, b } = {}) => `${a}${b}`) : (input: { a?: number; b?: string; }[]) => string[] +>input : { a?: number; b?: string; }[] +>a : number | undefined +>b : string | undefined +>input.map(({ a, b } = {}) => `${a}${b}`) : string[] +>input.map : (callbackfn: (value: { a?: number; b?: string; }, index: number, array: { a?: number; b?: string; }[]) => U, thisArg?: any) => U[] +>input : { a?: number; b?: string; }[] +>map : (callbackfn: (value: { a?: number; b?: string; }, index: number, array: { a?: number; b?: string; }[]) => U, thisArg?: any) => U[] +>({ a, b } = {}) => `${a}${b}` : ({ a, b }?: { a?: number; b?: string; }) => string +>a : number | undefined +>b : string | undefined +>{} : {} +>`${a}${b}` : string +>a : number | undefined +>b : string | undefined + diff --git a/tsc/testdata/tests/cases/compiler/objectBindingPatternDefaultMissingElements.ts b/tsc/testdata/tests/cases/compiler/objectBindingPatternDefaultMissingElements.ts index cc1004369b766..bc71002647daf 100644 --- a/tsc/testdata/tests/cases/compiler/objectBindingPatternDefaultMissingElements.ts +++ b/tsc/testdata/tests/cases/compiler/objectBindingPatternDefaultMissingElements.ts @@ -100,3 +100,7 @@ f10({ a: 1 }, ({ a } = {}) => { export const f11: (input?: { a?: number }[]) => void = ([...[{ a } = {}]] = []) => { const b: string = a; }; + +export const f12: (input: { a: boolean; b?: string }) => string = ({ a, b } = { a: false }) => `${a}${b}`; + +export const f13 = (input: { a?: number; b?: string }[]) => input.map(({ a, b } = {}) => `${a}${b}`);