diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 508f6bb323706..4f80bcb783442 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11460,7 +11460,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(widenTypeInferredFromInitializer(element, checkDeclarationInitializer(element, reportErrors ? CheckMode.Normal : CheckMode.Contextual, contextualType))); } if (isBindingPattern(element.name)) { return getTypeFromBindingPattern(element.name, includePatternInType, reportErrors); @@ -11618,16 +11618,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return false; } - function getTypeOfVariableOrParameterOrProperty(symbol: Symbol): Type { + function getTypeOfVariableOrParameterOrProperty(symbol: Symbol, checkMode?: CheckMode): Type { const links = getSymbolLinks(symbol); if (!links.type) { - const type = getTypeOfVariableOrParameterOrPropertyWorker(symbol); + const type = getTypeOfVariableOrParameterOrPropertyWorker(symbol, checkMode); // For a contextually typed parameter it is possible that a type has already // been assigned (in assignTypeToParameterAndFixTypeParameters), and we want // to preserve this type. In fact, we need to _prefer_ that type, but it won't // be assigned until contextual typing is complete, so we need to defer in // cases where contextual typing may take place. - if (!links.type && !isParameterOfContextSensitiveSignature(symbol)) { + if (!links.type && !isParameterOfContextSensitiveSignature(symbol) && !checkMode) { links.type = type; } return type; @@ -11635,7 +11635,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return links.type; } - function getTypeOfVariableOrParameterOrPropertyWorker(symbol: Symbol): Type { + function getTypeOfVariableOrParameterOrPropertyWorker(symbol: Symbol, checkMode?: CheckMode): Type { // Handle prototype property if (symbol.flags & SymbolFlags.Prototype) { return getTypeOfPrototypeProperty(symbol); @@ -11678,6 +11678,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (symbol.flags & SymbolFlags.ValueModule && !(symbol.flags & SymbolFlags.Assignment)) { return getTypeOfFuncClassEnumModule(symbol); } + + // When trying to get the *contextual* type of a binding element, it's possible to fall in a loop and therefore + // end up in a circularity-like situation. This is not a true circularity so we should not report such an error. + // For example, here the looping could happen when trying to get the type of `a` (binding element): + // + // const { a, b = a } = { a: 0 } + // + if (isBindingElement(declaration) && checkMode === CheckMode.Contextual) { + return errorType; + } return reportCircularityError(symbol); } let type: Type; @@ -11750,6 +11760,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (symbol.flags & SymbolFlags.ValueModule && !(symbol.flags & SymbolFlags.Assignment)) { return getTypeOfFuncClassEnumModule(symbol); } + + // When trying to get the *contextual* type of a binding element, it's possible to fall in a loop and therefore + // end up in a circularity-like situation. This is not a true circularity so we should not report such an error. + // For example, here the looping could happen when trying to get the type of `a` (binding element): + // + // const { a, b = a } = { a: 0 } + // + if (isBindingElement(declaration) && checkMode === CheckMode.Contextual) { + return type; + } return reportCircularityError(symbol); } return type; @@ -12032,7 +12052,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return getTypeOfSymbol(symbol); } - function getTypeOfSymbol(symbol: Symbol): Type { + function getTypeOfSymbol(symbol: Symbol, checkMode?: CheckMode): Type { const checkFlags = getCheckFlags(symbol); if (checkFlags & CheckFlags.DeferredType) { return getTypeOfSymbolWithDeferredType(symbol); @@ -12047,7 +12067,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return getTypeOfReverseMappedSymbol(symbol as ReverseMappedSymbol); } if (symbol.flags & (SymbolFlags.Variable | SymbolFlags.Property)) { - return getTypeOfVariableOrParameterOrProperty(symbol); + return getTypeOfVariableOrParameterOrProperty(symbol, checkMode); } if (symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.Enum | SymbolFlags.ValueModule)) { return getTypeOfFuncClassEnumModule(symbol); @@ -29069,8 +29089,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function getNarrowedTypeOfSymbol(symbol: Symbol, location: Identifier) { - const type = getTypeOfSymbol(symbol); + function getNarrowedTypeOfSymbol(symbol: Symbol, location: Identifier, checkMode?: CheckMode) { + const type = getTypeOfSymbol(symbol, checkMode); const declaration = symbol.valueDeclaration; if (declaration) { // If we have a non-rest binding element with no initializer declared as a const variable or a const-like @@ -29233,7 +29253,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { checkNestedBlockScopedBinding(node, symbol); - let type = getNarrowedTypeOfSymbol(localOrExportSymbol, node); + let type = getNarrowedTypeOfSymbol(localOrExportSymbol, node, checkMode); const assignmentKind = getAssignmentTargetKind(node); if (assignmentKind) { diff --git a/tests/baselines/reference/destructuringArrayBindingPatternAndAssignment3.types b/tests/baselines/reference/destructuringArrayBindingPatternAndAssignment3.types index 72aaa6378e5af..791ba83c243dc 100644 --- a/tests/baselines/reference/destructuringArrayBindingPatternAndAssignment3.types +++ b/tests/baselines/reference/destructuringArrayBindingPatternAndAssignment3.types @@ -2,16 +2,16 @@ === destructuringArrayBindingPatternAndAssignment3.ts === const [a, b = a] = [1]; // ok ->a : any ->b : any ->a : any +>a : number +>b : number +>a : number >[1] : [number] >1 : 1 const [c, d = c, e = e] = [1]; // error for e = e ->c : any ->d : any ->c : any +>c : number +>d : number +>c : number >e : any >e : any >[1] : [number] diff --git a/tests/baselines/reference/destructuringArrayBindingPatternAndAssignment5SiblingInitializer.js b/tests/baselines/reference/destructuringArrayBindingPatternAndAssignment5SiblingInitializer.js new file mode 100644 index 0000000000000..47eaab26cd17b --- /dev/null +++ b/tests/baselines/reference/destructuringArrayBindingPatternAndAssignment5SiblingInitializer.js @@ -0,0 +1,48 @@ +//// [tests/cases/conformance/es6/destructuring/destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts] //// + +//// [destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts] +// To be inferred as `number` +function f1() { + const [a1, b1 = a1] = [1]; + const [a2, b2 = 1 + a2] = [1]; +} + +// To be inferred as `string` +function f2() { + const [a1, b1 = a1] = ['hi']; + const [a2, b2 = a2 + '!'] = ['hi']; +} + +// To be inferred as `string | number` +function f3() { + const [a1, b1 = a1] = ['hi', 1]; + const [a2, b2 = a2 + '!'] = ['hi', 1]; +} + +// Based on comment: +// - https://github.com/microsoft/TypeScript/issues/49989#issuecomment-1852694486 +declare const yadda: [number, number] | undefined +function f4() { + const [ a, b = a ] = yadda ?? []; +} + + +//// [destructuringArrayBindingPatternAndAssignment5SiblingInitializer.js] +// To be inferred as `number` +function f1() { + var _a = [1], a1 = _a[0], _b = _a[1], b1 = _b === void 0 ? a1 : _b; + var _c = [1], a2 = _c[0], _d = _c[1], b2 = _d === void 0 ? 1 + a2 : _d; +} +// To be inferred as `string` +function f2() { + var _a = ['hi'], a1 = _a[0], _b = _a[1], b1 = _b === void 0 ? a1 : _b; + var _c = ['hi'], a2 = _c[0], _d = _c[1], b2 = _d === void 0 ? a2 + '!' : _d; +} +// To be inferred as `string | number` +function f3() { + var _a = ['hi', 1], a1 = _a[0], _b = _a[1], b1 = _b === void 0 ? a1 : _b; + var _c = ['hi', 1], a2 = _c[0], _d = _c[1], b2 = _d === void 0 ? a2 + '!' : _d; +} +function f4() { + var _a = yadda !== null && yadda !== void 0 ? yadda : [], a = _a[0], _b = _a[1], b = _b === void 0 ? a : _b; +} diff --git a/tests/baselines/reference/destructuringArrayBindingPatternAndAssignment5SiblingInitializer.symbols b/tests/baselines/reference/destructuringArrayBindingPatternAndAssignment5SiblingInitializer.symbols new file mode 100644 index 0000000000000..2ff79c20083f2 --- /dev/null +++ b/tests/baselines/reference/destructuringArrayBindingPatternAndAssignment5SiblingInitializer.symbols @@ -0,0 +1,63 @@ +//// [tests/cases/conformance/es6/destructuring/destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts] //// + +=== destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts === +// To be inferred as `number` +function f1() { +>f1 : Symbol(f1, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 0, 0)) + + const [a1, b1 = a1] = [1]; +>a1 : Symbol(a1, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 2, 11)) +>b1 : Symbol(b1, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 2, 14)) +>a1 : Symbol(a1, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 2, 11)) + + const [a2, b2 = 1 + a2] = [1]; +>a2 : Symbol(a2, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 3, 11)) +>b2 : Symbol(b2, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 3, 14)) +>a2 : Symbol(a2, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 3, 11)) +} + +// To be inferred as `string` +function f2() { +>f2 : Symbol(f2, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 4, 1)) + + const [a1, b1 = a1] = ['hi']; +>a1 : Symbol(a1, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 8, 11)) +>b1 : Symbol(b1, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 8, 14)) +>a1 : Symbol(a1, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 8, 11)) + + const [a2, b2 = a2 + '!'] = ['hi']; +>a2 : Symbol(a2, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 9, 11)) +>b2 : Symbol(b2, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 9, 14)) +>a2 : Symbol(a2, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 9, 11)) +} + +// To be inferred as `string | number` +function f3() { +>f3 : Symbol(f3, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 10, 1)) + + const [a1, b1 = a1] = ['hi', 1]; +>a1 : Symbol(a1, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 14, 11)) +>b1 : Symbol(b1, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 14, 14)) +>a1 : Symbol(a1, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 14, 11)) + + const [a2, b2 = a2 + '!'] = ['hi', 1]; +>a2 : Symbol(a2, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 15, 11)) +>b2 : Symbol(b2, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 15, 14)) +>a2 : Symbol(a2, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 15, 11)) +} + +// Based on comment: +// - https://github.com/microsoft/TypeScript/issues/49989#issuecomment-1852694486 +declare const yadda: [number, number] | undefined +>yadda : Symbol(yadda, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 20, 13)) + +function f4() { +>f4 : Symbol(f4, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 20, 49)) + + const [ a, b = a ] = yadda ?? []; +>a : Symbol(a, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 22, 11)) +>b : Symbol(b, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 22, 14)) +>a : Symbol(a, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 22, 11)) +>yadda : Symbol(yadda, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 20, 13)) +} + diff --git a/tests/baselines/reference/destructuringArrayBindingPatternAndAssignment5SiblingInitializer.types b/tests/baselines/reference/destructuringArrayBindingPatternAndAssignment5SiblingInitializer.types new file mode 100644 index 0000000000000..009a62ee2d987 --- /dev/null +++ b/tests/baselines/reference/destructuringArrayBindingPatternAndAssignment5SiblingInitializer.types @@ -0,0 +1,85 @@ +//// [tests/cases/conformance/es6/destructuring/destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts] //// + +=== destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts === +// To be inferred as `number` +function f1() { +>f1 : () => void + + const [a1, b1 = a1] = [1]; +>a1 : number +>b1 : number +>a1 : number +>[1] : [number] +>1 : 1 + + const [a2, b2 = 1 + a2] = [1]; +>a2 : number +>b2 : number +>1 + a2 : number +>1 : 1 +>a2 : number +>[1] : [number] +>1 : 1 +} + +// To be inferred as `string` +function f2() { +>f2 : () => void + + const [a1, b1 = a1] = ['hi']; +>a1 : string +>b1 : string +>a1 : string +>['hi'] : [string] +>'hi' : "hi" + + const [a2, b2 = a2 + '!'] = ['hi']; +>a2 : string +>b2 : string +>a2 + '!' : string +>a2 : string +>'!' : "!" +>['hi'] : [string] +>'hi' : "hi" +} + +// To be inferred as `string | number` +function f3() { +>f3 : () => void + + const [a1, b1 = a1] = ['hi', 1]; +>a1 : string +>b1 : string | number +>a1 : string +>['hi', 1] : [string, number] +>'hi' : "hi" +>1 : 1 + + const [a2, b2 = a2 + '!'] = ['hi', 1]; +>a2 : string +>b2 : string | number +>a2 + '!' : string +>a2 : string +>'!' : "!" +>['hi', 1] : [string, number] +>'hi' : "hi" +>1 : 1 +} + +// Based on comment: +// - https://github.com/microsoft/TypeScript/issues/49989#issuecomment-1852694486 +declare const yadda: [number, number] | undefined +>yadda : [number, number] + +function f4() { +>f4 : () => void + + const [ a, b = a ] = yadda ?? []; +>a : number +>b : number +>a : number +>yadda ?? [] : [number, number] | [] +>yadda : [number, number] +>[] : [] +} + diff --git a/tests/baselines/reference/destructuringObjectBindingPatternAndAssignment9SiblingInitializer.js b/tests/baselines/reference/destructuringObjectBindingPatternAndAssignment9SiblingInitializer.js new file mode 100644 index 0000000000000..92a7a56842bfc --- /dev/null +++ b/tests/baselines/reference/destructuringObjectBindingPatternAndAssignment9SiblingInitializer.js @@ -0,0 +1,48 @@ +//// [tests/cases/conformance/es6/destructuring/destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts] //// + +//// [destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts] +// To be inferred as `number` +function f1() { + const { a1, b1 = a1 } = { a1: 1 }; + const { a2, b2 = 1 + a2 } = { a2: 1 }; +} + +// To be inferred as `string` +function f2() { + const { a1, b1 = a1 } = { a1: 'hi' }; + const { a2, b2 = a2 + '!' } = { a2: 'hi' }; +} + +// To be inferred as `string | number` +function f3() { + const { a1, b1 = a1 } = { a1: 'hi', b1: 1 }; + const { a2, b2 = a2 + '!' } = { a2: 'hi', b2: 1 }; +} + +// Based on comment: +// - https://github.com/microsoft/TypeScript/issues/49989#issuecomment-1852694486 +declare const yadda: { a?: number, b?: number } | undefined +function f4() { + const { a, b = a } = yadda ?? {}; +} + + +//// [destructuringObjectBindingPatternAndAssignment9SiblingInitializer.js] +// To be inferred as `number` +function f1() { + var _a = { a1: 1 }, a1 = _a.a1, _b = _a.b1, b1 = _b === void 0 ? a1 : _b; + var _c = { a2: 1 }, a2 = _c.a2, _d = _c.b2, b2 = _d === void 0 ? 1 + a2 : _d; +} +// To be inferred as `string` +function f2() { + var _a = { a1: 'hi' }, a1 = _a.a1, _b = _a.b1, b1 = _b === void 0 ? a1 : _b; + var _c = { a2: 'hi' }, a2 = _c.a2, _d = _c.b2, b2 = _d === void 0 ? a2 + '!' : _d; +} +// To be inferred as `string | number` +function f3() { + var _a = { a1: 'hi', b1: 1 }, a1 = _a.a1, _b = _a.b1, b1 = _b === void 0 ? a1 : _b; + var _c = { a2: 'hi', b2: 1 }, a2 = _c.a2, _d = _c.b2, b2 = _d === void 0 ? a2 + '!' : _d; +} +function f4() { + var _a = yadda !== null && yadda !== void 0 ? yadda : {}, a = _a.a, _b = _a.b, b = _b === void 0 ? a : _b; +} diff --git a/tests/baselines/reference/destructuringObjectBindingPatternAndAssignment9SiblingInitializer.symbols b/tests/baselines/reference/destructuringObjectBindingPatternAndAssignment9SiblingInitializer.symbols new file mode 100644 index 0000000000000..3c76a5d2b045d --- /dev/null +++ b/tests/baselines/reference/destructuringObjectBindingPatternAndAssignment9SiblingInitializer.symbols @@ -0,0 +1,73 @@ +//// [tests/cases/conformance/es6/destructuring/destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts] //// + +=== destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts === +// To be inferred as `number` +function f1() { +>f1 : Symbol(f1, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 0, 0)) + + const { a1, b1 = a1 } = { a1: 1 }; +>a1 : Symbol(a1, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 2, 11)) +>b1 : Symbol(b1, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 2, 15)) +>a1 : Symbol(a1, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 2, 11)) +>a1 : Symbol(a1, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 2, 29)) + + const { a2, b2 = 1 + a2 } = { a2: 1 }; +>a2 : Symbol(a2, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 3, 11)) +>b2 : Symbol(b2, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 3, 15)) +>a2 : Symbol(a2, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 3, 11)) +>a2 : Symbol(a2, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 3, 33)) +} + +// To be inferred as `string` +function f2() { +>f2 : Symbol(f2, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 4, 1)) + + const { a1, b1 = a1 } = { a1: 'hi' }; +>a1 : Symbol(a1, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 8, 11)) +>b1 : Symbol(b1, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 8, 15)) +>a1 : Symbol(a1, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 8, 11)) +>a1 : Symbol(a1, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 8, 29)) + + const { a2, b2 = a2 + '!' } = { a2: 'hi' }; +>a2 : Symbol(a2, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 9, 11)) +>b2 : Symbol(b2, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 9, 15)) +>a2 : Symbol(a2, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 9, 11)) +>a2 : Symbol(a2, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 9, 35)) +} + +// To be inferred as `string | number` +function f3() { +>f3 : Symbol(f3, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 10, 1)) + + const { a1, b1 = a1 } = { a1: 'hi', b1: 1 }; +>a1 : Symbol(a1, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 14, 11)) +>b1 : Symbol(b1, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 14, 15)) +>a1 : Symbol(a1, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 14, 11)) +>a1 : Symbol(a1, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 14, 29)) +>b1 : Symbol(b1, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 14, 39)) + + const { a2, b2 = a2 + '!' } = { a2: 'hi', b2: 1 }; +>a2 : Symbol(a2, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 15, 11)) +>b2 : Symbol(b2, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 15, 15)) +>a2 : Symbol(a2, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 15, 11)) +>a2 : Symbol(a2, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 15, 35)) +>b2 : Symbol(b2, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 15, 45)) +} + +// Based on comment: +// - https://github.com/microsoft/TypeScript/issues/49989#issuecomment-1852694486 +declare const yadda: { a?: number, b?: number } | undefined +>yadda : Symbol(yadda, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 20, 13)) +>a : Symbol(a, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 20, 22)) +>b : Symbol(b, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 20, 34)) + +function f4() { +>f4 : Symbol(f4, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 20, 59)) + + const { a, b = a } = yadda ?? {}; +>a : Symbol(a, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 22, 11)) +>b : Symbol(b, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 22, 14)) +>a : Symbol(a, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 22, 11)) +>yadda : Symbol(yadda, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 20, 13)) +} + diff --git a/tests/baselines/reference/destructuringObjectBindingPatternAndAssignment9SiblingInitializer.types b/tests/baselines/reference/destructuringObjectBindingPatternAndAssignment9SiblingInitializer.types new file mode 100644 index 0000000000000..c5ebaabe82453 --- /dev/null +++ b/tests/baselines/reference/destructuringObjectBindingPatternAndAssignment9SiblingInitializer.types @@ -0,0 +1,95 @@ +//// [tests/cases/conformance/es6/destructuring/destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts] //// + +=== destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts === +// To be inferred as `number` +function f1() { +>f1 : () => void + + const { a1, b1 = a1 } = { a1: 1 }; +>a1 : number +>b1 : number +>a1 : number +>{ a1: 1 } : { a1: number; b1?: number; } +>a1 : number +>1 : 1 + + const { a2, b2 = 1 + a2 } = { a2: 1 }; +>a2 : number +>b2 : number +>1 + a2 : number +>1 : 1 +>a2 : number +>{ a2: 1 } : { a2: number; b2?: number; } +>a2 : number +>1 : 1 +} + +// To be inferred as `string` +function f2() { +>f2 : () => void + + const { a1, b1 = a1 } = { a1: 'hi' }; +>a1 : string +>b1 : string +>a1 : string +>{ a1: 'hi' } : { a1: string; b1?: string; } +>a1 : string +>'hi' : "hi" + + const { a2, b2 = a2 + '!' } = { a2: 'hi' }; +>a2 : string +>b2 : string +>a2 + '!' : string +>a2 : string +>'!' : "!" +>{ a2: 'hi' } : { a2: string; b2?: string; } +>a2 : string +>'hi' : "hi" +} + +// To be inferred as `string | number` +function f3() { +>f3 : () => void + + const { a1, b1 = a1 } = { a1: 'hi', b1: 1 }; +>a1 : string +>b1 : string | number +>a1 : string +>{ a1: 'hi', b1: 1 } : { a1: string; b1?: number; } +>a1 : string +>'hi' : "hi" +>b1 : number +>1 : 1 + + const { a2, b2 = a2 + '!' } = { a2: 'hi', b2: 1 }; +>a2 : string +>b2 : string | number +>a2 + '!' : string +>a2 : string +>'!' : "!" +>{ a2: 'hi', b2: 1 } : { a2: string; b2?: number; } +>a2 : string +>'hi' : "hi" +>b2 : number +>1 : 1 +} + +// Based on comment: +// - https://github.com/microsoft/TypeScript/issues/49989#issuecomment-1852694486 +declare const yadda: { a?: number, b?: number } | undefined +>yadda : { a?: number; b?: number; } +>a : number +>b : number + +function f4() { +>f4 : () => void + + const { a, b = a } = yadda ?? {}; +>a : number +>b : number +>a : number +>yadda ?? {} : { a?: number; b?: number; } +>yadda : { a?: number; b?: number; } +>{} : {} +} + diff --git a/tests/cases/conformance/es6/destructuring/destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts b/tests/cases/conformance/es6/destructuring/destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts new file mode 100644 index 0000000000000..6183e22b61fbf --- /dev/null +++ b/tests/cases/conformance/es6/destructuring/destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts @@ -0,0 +1,26 @@ +// @noImplicitAny: true + +// To be inferred as `number` +function f1() { + const [a1, b1 = a1] = [1]; + const [a2, b2 = 1 + a2] = [1]; +} + +// To be inferred as `string` +function f2() { + const [a1, b1 = a1] = ['hi']; + const [a2, b2 = a2 + '!'] = ['hi']; +} + +// To be inferred as `string | number` +function f3() { + const [a1, b1 = a1] = ['hi', 1]; + const [a2, b2 = a2 + '!'] = ['hi', 1]; +} + +// Based on comment: +// - https://github.com/microsoft/TypeScript/issues/49989#issuecomment-1852694486 +declare const yadda: [number, number] | undefined +function f4() { + const [ a, b = a ] = yadda ?? []; +} diff --git a/tests/cases/conformance/es6/destructuring/destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts b/tests/cases/conformance/es6/destructuring/destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts new file mode 100644 index 0000000000000..d4d5cd7c6cd4d --- /dev/null +++ b/tests/cases/conformance/es6/destructuring/destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts @@ -0,0 +1,26 @@ +// @noImplicitAny: true + +// To be inferred as `number` +function f1() { + const { a1, b1 = a1 } = { a1: 1 }; + const { a2, b2 = 1 + a2 } = { a2: 1 }; +} + +// To be inferred as `string` +function f2() { + const { a1, b1 = a1 } = { a1: 'hi' }; + const { a2, b2 = a2 + '!' } = { a2: 'hi' }; +} + +// To be inferred as `string | number` +function f3() { + const { a1, b1 = a1 } = { a1: 'hi', b1: 1 }; + const { a2, b2 = a2 + '!' } = { a2: 'hi', b2: 1 }; +} + +// Based on comment: +// - https://github.com/microsoft/TypeScript/issues/49989#issuecomment-1852694486 +declare const yadda: { a?: number, b?: number } | undefined +function f4() { + const { a, b = a } = yadda ?? {}; +}