diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 23c5568f2e5..c3b04af565f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4919,7 +4919,7 @@ namespace ts { if (strictNullChecks && declaration.initializer && !(getFalsyFlags(checkDeclarationInitializer(declaration)) & TypeFlags.Undefined)) { type = getTypeWithFacts(type, TypeFacts.NEUndefined); } - return declaration.initializer && !getContextualTypeForVariableLikeDeclaration(walkUpBindingElementsAndPatterns(declaration)) ? + return declaration.initializer && !getEffectiveTypeAnnotationNode(walkUpBindingElementsAndPatterns(declaration)) ? getUnionType([type, checkDeclarationInitializer(declaration)], UnionReduction.Subtype) : type; } @@ -22810,7 +22810,8 @@ namespace ts { const type = getTypeOfExpression(initializer, /*cache*/ true); const widened = getCombinedNodeFlags(declaration) & NodeFlags.Const || isDeclarationReadonly(declaration) || - isTypeAssertion(initializer) ? type : getWidenedLiteralType(type); + isTypeAssertion(initializer) || + isLiteralOfContextualType(type, getContextualType(initializer)) ? type : getWidenedLiteralType(type); if (isInJSFile(declaration)) { if (widened.flags & TypeFlags.Nullable) { reportImplicitAny(declaration, anyType); diff --git a/tests/baselines/reference/destructuringArrayBindingPatternAndAssignment3.types b/tests/baselines/reference/destructuringArrayBindingPatternAndAssignment3.types index 389b6b5e5f5..0fb81ba6aa3 100644 --- a/tests/baselines/reference/destructuringArrayBindingPatternAndAssignment3.types +++ b/tests/baselines/reference/destructuringArrayBindingPatternAndAssignment3.types @@ -45,8 +45,8 @@ const [f, g = f, h = i, i = f] = [1]; // error for h = i >c : number >d : number >c : number ->e : number ->e : number +>e : any +>e : any })([1]); >[1] : number[] diff --git a/tests/baselines/reference/destructuringInitializerContextualTypeFromContext.js b/tests/baselines/reference/destructuringInitializerContextualTypeFromContext.js index 2dd6b4ea11a..1215d343df0 100644 --- a/tests/baselines/reference/destructuringInitializerContextualTypeFromContext.js +++ b/tests/baselines/reference/destructuringInitializerContextualTypeFromContext.js @@ -17,9 +17,16 @@ const Child: SFC = ({ children, name = "Artemis", ...props -}) => `name: ${name} props: ${JSON.stringify(props)}`; +}) => `name: ${name} props: ${JSON.stringify(props)}`; + +// Repro from #29189 + +declare function f(g: (as: string[]) => void): void +f(([_1, _2 = undefined]) => undefined) + //// [destructuringInitializerContextualTypeFromContext.js] +"use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { @@ -48,3 +55,7 @@ var Child = function (_a) { var children = _a.children, _b = _a.name, name = _b === void 0 ? "Artemis" : _b, props = __rest(_a, ["children", "name"]); return "name: " + name + " props: " + JSON.stringify(props); }; +f(function (_a) { + var _1 = _a[0], _b = _a[1], _2 = _b === void 0 ? undefined : _b; + return undefined; +}); diff --git a/tests/baselines/reference/destructuringInitializerContextualTypeFromContext.symbols b/tests/baselines/reference/destructuringInitializerContextualTypeFromContext.symbols index 317a09ee105..8ae1b56e20f 100644 --- a/tests/baselines/reference/destructuringInitializerContextualTypeFromContext.symbols +++ b/tests/baselines/reference/destructuringInitializerContextualTypeFromContext.symbols @@ -56,3 +56,17 @@ const Child: SFC = ({ >stringify : Symbol(JSON.stringify, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) >props : Symbol(props, Decl(destructuringInitializerContextualTypeFromContext.ts, 16, 21)) +// Repro from #29189 + +declare function f(g: (as: string[]) => void): void +>f : Symbol(f, Decl(destructuringInitializerContextualTypeFromContext.ts, 18, 54)) +>g : Symbol(g, Decl(destructuringInitializerContextualTypeFromContext.ts, 22, 19)) +>as : Symbol(as, Decl(destructuringInitializerContextualTypeFromContext.ts, 22, 23)) + +f(([_1, _2 = undefined]) => undefined) +>f : Symbol(f, Decl(destructuringInitializerContextualTypeFromContext.ts, 18, 54)) +>_1 : Symbol(_1, Decl(destructuringInitializerContextualTypeFromContext.ts, 23, 4)) +>_2 : Symbol(_2, Decl(destructuringInitializerContextualTypeFromContext.ts, 23, 7)) +>undefined : Symbol(undefined) +>undefined : Symbol(undefined) + diff --git a/tests/baselines/reference/destructuringInitializerContextualTypeFromContext.types b/tests/baselines/reference/destructuringInitializerContextualTypeFromContext.types index fa76e2eef25..4018d4bed3f 100644 --- a/tests/baselines/reference/destructuringInitializerContextualTypeFromContext.types +++ b/tests/baselines/reference/destructuringInitializerContextualTypeFromContext.types @@ -50,8 +50,24 @@ const Child: SFC = ({ >`name: ${name} props: ${JSON.stringify(props)}` : string >name : "Apollo" | "Artemis" | "Dionysus" | "Persephone" >JSON.stringify(props) : string ->JSON.stringify : { (value: any, replacer?: (key: string, value: any) => any, space?: string | number): string; (value: any, replacer?: (string | number)[], space?: string | number): string; } +>JSON.stringify : { (value: any, replacer?: ((key: string, value: any) => any) | undefined, space?: string | number | undefined): string; (value: any, replacer?: (string | number)[] | null | undefined, space?: string | number | undefined): string; } >JSON : JSON ->stringify : { (value: any, replacer?: (key: string, value: any) => any, space?: string | number): string; (value: any, replacer?: (string | number)[], space?: string | number): string; } +>stringify : { (value: any, replacer?: ((key: string, value: any) => any) | undefined, space?: string | number | undefined): string; (value: any, replacer?: (string | number)[] | null | undefined, space?: string | number | undefined): string; } >props : {} +// Repro from #29189 + +declare function f(g: (as: string[]) => void): void +>f : (g: (as: string[]) => void) => void +>g : (as: string[]) => void +>as : string[] + +f(([_1, _2 = undefined]) => undefined) +>f(([_1, _2 = undefined]) => undefined) : void +>f : (g: (as: string[]) => void) => void +>([_1, _2 = undefined]) => undefined : ([_1, _2]: string[]) => undefined +>_1 : string +>_2 : string | undefined +>undefined : undefined +>undefined : undefined + diff --git a/tests/cases/compiler/destructuringInitializerContextualTypeFromContext.ts b/tests/cases/compiler/destructuringInitializerContextualTypeFromContext.ts index 6153b1e3a80..6b109e22271 100644 --- a/tests/cases/compiler/destructuringInitializerContextualTypeFromContext.ts +++ b/tests/cases/compiler/destructuringInitializerContextualTypeFromContext.ts @@ -1,3 +1,5 @@ +// @strict: true + interface SFC

{ (props: P & { children?: any }): any | null; } @@ -16,4 +18,9 @@ const Child: SFC = ({ children, name = "Artemis", ...props -}) => `name: ${name} props: ${JSON.stringify(props)}`; \ No newline at end of file +}) => `name: ${name} props: ${JSON.stringify(props)}`; + +// Repro from #29189 + +declare function f(g: (as: string[]) => void): void +f(([_1, _2 = undefined]) => undefined)