diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6385d150a3e8e..33943fa06604a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4862,17 +4862,8 @@ namespace ts { function getTypeForBindingElement(declaration: BindingElement): Type | undefined { const pattern = declaration.parent; let parentType = getTypeForBindingElementParent(pattern.parent); - // If parent has the unknown (error) type, then so does this binding element - if (parentType === errorType) { - return errorType; - } - // If no type was specified or inferred for parent, - // infer from the initializer of the binding element if one is present. - // Otherwise, go with the undefined type of the parent. - if (!parentType) { - return declaration.initializer ? checkDeclarationInitializer(declaration) : parentType; - } - if (isTypeAny(parentType)) { + // If no type or an any type was inferred for parent, infer that for the binding element + if (!parentType || isTypeAny(parentType)) { return parentType; } // Relax null check on ambient destructuring parameters, since the parameters have no implementation and are just documentation @@ -4958,6 +4949,12 @@ namespace ts { return strictNullChecks && optional ? getOptionalType(type) : type; } + function isParameterOfContextuallyTypedFunction(node: Declaration) { + return node.kind === SyntaxKind.Parameter && + (node.parent.kind === SyntaxKind.FunctionExpression || node.parent.kind === SyntaxKind.ArrowFunction) && + !!getContextualType(node.parent); + } + // Return the inferred type for a variable, parameter, or property declaration function getTypeForVariableLikeDeclaration(declaration: ParameterDeclaration | PropertyDeclaration | PropertySignature | VariableDeclaration | BindingElement, includeOptionality: boolean): Type | undefined { // A variable declared in a for..in statement is of type string, or of type keyof T when the @@ -5041,8 +5038,9 @@ namespace ts { } } - // Use the type of the initializer expression if one is present - if (declaration.initializer) { + // Use the type of the initializer expression if one is present and the declaration is + // not a parameter of a contextually typed function + if (declaration.initializer && !isParameterOfContextuallyTypedFunction(declaration)) { const type = checkDeclarationInitializer(declaration); return addOptionality(type, isOptional); } @@ -5053,8 +5051,9 @@ namespace ts { return trueType; } - // If the declaration specifies a binding pattern, use the type implied by the binding pattern - if (isBindingPattern(declaration.name)) { + // If the declaration specifies a binding pattern and is not a parameter of a contextually + // typed function, use the type implied by the binding pattern + if (isBindingPattern(declaration.name) && !isParameterOfContextuallyTypedFunction(declaration)) { return getTypeFromBindingPattern(declaration.name, /*includePatternInType*/ false, /*reportErrors*/ true); } @@ -5691,17 +5690,21 @@ namespace ts { } function reportCircularityError(symbol: Symbol) { + const declaration = symbol.valueDeclaration; // Check if variable has type annotation that circularly references the variable itself - if (getEffectiveTypeAnnotationNode(symbol.valueDeclaration)) { + if (getEffectiveTypeAnnotationNode(declaration)) { error(symbol.valueDeclaration, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation, symbolToString(symbol)); return errorType; } - // Otherwise variable has initializer that circularly references the variable itself - if (noImplicitAny) { + // Check if variable has initializer that circularly references the variable itself + if (noImplicitAny && (declaration.kind !== SyntaxKind.Parameter || (declaration).initializer)) { error(symbol.valueDeclaration, Diagnostics._0_implicitly_has_type_any_because_it_does_not_have_a_type_annotation_and_is_referenced_directly_or_indirectly_in_its_own_initializer, symbolToString(symbol)); } + // Circularities could also result from parameters in function expressions that end up + // having themselves as contextual types following type argument inference. In those cases + // we have already reported an implicit any error so we don't report anything here. return anyType; } @@ -25652,7 +25655,7 @@ namespace ts { const parent = node.parent.parent; const parentType = getTypeForBindingElementParent(parent); const name = node.propertyName || node.name; - if (!isBindingPattern(name) && parentType) { + if (parentType && !isBindingPattern(name)) { const exprType = getLiteralTypeFromPropertyName(name); if (isTypeUsableAsPropertyName(exprType)) { const nameText = getPropertyNameFromType(exprType); diff --git a/tests/baselines/reference/contextuallyTypedParametersWithInitializers.errors.txt b/tests/baselines/reference/contextuallyTypedParametersWithInitializers.errors.txt new file mode 100644 index 0000000000000..61bb8b765b61e --- /dev/null +++ b/tests/baselines/reference/contextuallyTypedParametersWithInitializers.errors.txt @@ -0,0 +1,42 @@ +tests/cases/compiler/contextuallyTypedParametersWithInitializers.ts(8,29): error TS7031: Binding element 'foo' implicitly has an 'any' type. +tests/cases/compiler/contextuallyTypedParametersWithInitializers.ts(14,27): error TS7006: Parameter 'foo' implicitly has an 'any' type. +tests/cases/compiler/contextuallyTypedParametersWithInitializers.ts(27,42): error TS7031: Binding element 'foo' implicitly has an 'any' type. + + +==== tests/cases/compiler/contextuallyTypedParametersWithInitializers.ts (3 errors) ==== + declare function id1(input: T): T; + declare function id2 any>(input: T): T; + declare function id3 any>(input: T): T; + declare function id4 any>(input: T): T; + declare function id5 any>(input: T): T; + + const f10 = function ({ foo = 42 }) { return foo }; + const f11 = id1(function ({ foo = 42 }) { return foo }); // Implicit any error + ~~~ +!!! error TS7031: Binding element 'foo' implicitly has an 'any' type. + const f12 = id2(function ({ foo = 42 }) { return foo }); + const f13 = id3(function ({ foo = 42 }) { return foo }); + const f14 = id4(function ({ foo = 42 }) { return foo }); + + const f20 = function (foo = 42) { return foo }; + const f21 = id1(function (foo = 42) { return foo }); // Implicit any error + ~~~~~~~~ +!!! error TS7006: Parameter 'foo' implicitly has an 'any' type. + const f22 = id2(function (foo = 42) { return foo }); + const f25 = id5(function (foo = 42) { return foo }); + + // Repro from #28816 + + function id(input: T): T { return input } + + function getFoo ({ foo = 42 }) { + return foo; + } + + const newGetFoo = id(getFoo); + const newGetFoo2 = id(function getFoo ({ foo = 42 }) { + ~~~ +!!! error TS7031: Binding element 'foo' implicitly has an 'any' type. + return foo; + }); + \ No newline at end of file diff --git a/tests/baselines/reference/contextuallyTypedParametersWithInitializers.js b/tests/baselines/reference/contextuallyTypedParametersWithInitializers.js new file mode 100644 index 0000000000000..96b55c431572e --- /dev/null +++ b/tests/baselines/reference/contextuallyTypedParametersWithInitializers.js @@ -0,0 +1,114 @@ +//// [contextuallyTypedParametersWithInitializers.ts] +declare function id1(input: T): T; +declare function id2 any>(input: T): T; +declare function id3 any>(input: T): T; +declare function id4 any>(input: T): T; +declare function id5 any>(input: T): T; + +const f10 = function ({ foo = 42 }) { return foo }; +const f11 = id1(function ({ foo = 42 }) { return foo }); // Implicit any error +const f12 = id2(function ({ foo = 42 }) { return foo }); +const f13 = id3(function ({ foo = 42 }) { return foo }); +const f14 = id4(function ({ foo = 42 }) { return foo }); + +const f20 = function (foo = 42) { return foo }; +const f21 = id1(function (foo = 42) { return foo }); // Implicit any error +const f22 = id2(function (foo = 42) { return foo }); +const f25 = id5(function (foo = 42) { return foo }); + +// Repro from #28816 + +function id(input: T): T { return input } + +function getFoo ({ foo = 42 }) { + return foo; +} + +const newGetFoo = id(getFoo); +const newGetFoo2 = id(function getFoo ({ foo = 42 }) { + return foo; +}); + + +//// [contextuallyTypedParametersWithInitializers.js] +"use strict"; +var f10 = function (_a) { + var _b = _a.foo, foo = _b === void 0 ? 42 : _b; + return foo; +}; +var f11 = id1(function (_a) { + var _b = _a.foo, foo = _b === void 0 ? 42 : _b; + return foo; +}); // Implicit any error +var f12 = id2(function (_a) { + var _b = _a.foo, foo = _b === void 0 ? 42 : _b; + return foo; +}); +var f13 = id3(function (_a) { + var _b = _a.foo, foo = _b === void 0 ? 42 : _b; + return foo; +}); +var f14 = id4(function (_a) { + var _b = _a.foo, foo = _b === void 0 ? 42 : _b; + return foo; +}); +var f20 = function (foo) { + if (foo === void 0) { foo = 42; } + return foo; +}; +var f21 = id1(function (foo) { + if (foo === void 0) { foo = 42; } + return foo; +}); // Implicit any error +var f22 = id2(function (foo) { + if (foo === void 0) { foo = 42; } + return foo; +}); +var f25 = id5(function (foo) { + if (foo === void 0) { foo = 42; } + return foo; +}); +// Repro from #28816 +function id(input) { return input; } +function getFoo(_a) { + var _b = _a.foo, foo = _b === void 0 ? 42 : _b; + return foo; +} +var newGetFoo = id(getFoo); +var newGetFoo2 = id(function getFoo(_a) { + var _b = _a.foo, foo = _b === void 0 ? 42 : _b; + return foo; +}); + + +//// [contextuallyTypedParametersWithInitializers.d.ts] +declare function id1(input: T): T; +declare function id2 any>(input: T): T; +declare function id3 any>(input: T): T; +declare function id4 any>(input: T): T; +declare function id5 any>(input: T): T; +declare const f10: ({ foo }: { + foo?: number | undefined; +}) => number; +declare const f11: ({ foo }: any) => any; +declare const f12: ({ foo }: any) => any; +declare const f13: ({ foo }: { + foo: any; +}) => any; +declare const f14: ({ foo }: { + foo?: number | undefined; +}) => number; +declare const f20: (foo?: number) => number; +declare const f21: (foo?: any) => any; +declare const f22: (foo?: any) => any; +declare const f25: (foo?: number | undefined) => number; +declare function id(input: T): T; +declare function getFoo({ foo }: { + foo?: number | undefined; +}): number; +declare const newGetFoo: typeof getFoo; +declare const newGetFoo2: ({ foo }: any) => any; diff --git a/tests/baselines/reference/contextuallyTypedParametersWithInitializers.symbols b/tests/baselines/reference/contextuallyTypedParametersWithInitializers.symbols new file mode 100644 index 0000000000000..6932f7b0cb8fc --- /dev/null +++ b/tests/baselines/reference/contextuallyTypedParametersWithInitializers.symbols @@ -0,0 +1,128 @@ +=== tests/cases/compiler/contextuallyTypedParametersWithInitializers.ts === +declare function id1(input: T): T; +>id1 : Symbol(id1, Decl(contextuallyTypedParametersWithInitializers.ts, 0, 0)) +>T : Symbol(T, Decl(contextuallyTypedParametersWithInitializers.ts, 0, 21)) +>input : Symbol(input, Decl(contextuallyTypedParametersWithInitializers.ts, 0, 24)) +>T : Symbol(T, Decl(contextuallyTypedParametersWithInitializers.ts, 0, 21)) +>T : Symbol(T, Decl(contextuallyTypedParametersWithInitializers.ts, 0, 21)) + +declare function id2 any>(input: T): T; +>id2 : Symbol(id2, Decl(contextuallyTypedParametersWithInitializers.ts, 0, 37)) +>T : Symbol(T, Decl(contextuallyTypedParametersWithInitializers.ts, 1, 21)) +>x : Symbol(x, Decl(contextuallyTypedParametersWithInitializers.ts, 1, 32)) +>input : Symbol(input, Decl(contextuallyTypedParametersWithInitializers.ts, 1, 48)) +>T : Symbol(T, Decl(contextuallyTypedParametersWithInitializers.ts, 1, 21)) +>T : Symbol(T, Decl(contextuallyTypedParametersWithInitializers.ts, 1, 21)) + +declare function id3 any>(input: T): T; +>id3 : Symbol(id3, Decl(contextuallyTypedParametersWithInitializers.ts, 1, 61)) +>T : Symbol(T, Decl(contextuallyTypedParametersWithInitializers.ts, 2, 21)) +>x : Symbol(x, Decl(contextuallyTypedParametersWithInitializers.ts, 2, 32)) +>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 2, 36)) +>input : Symbol(input, Decl(contextuallyTypedParametersWithInitializers.ts, 2, 57)) +>T : Symbol(T, Decl(contextuallyTypedParametersWithInitializers.ts, 2, 21)) +>T : Symbol(T, Decl(contextuallyTypedParametersWithInitializers.ts, 2, 21)) + +declare function id4 any>(input: T): T; +>id4 : Symbol(id4, Decl(contextuallyTypedParametersWithInitializers.ts, 2, 70)) +>T : Symbol(T, Decl(contextuallyTypedParametersWithInitializers.ts, 3, 21)) +>x : Symbol(x, Decl(contextuallyTypedParametersWithInitializers.ts, 3, 32)) +>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 3, 36)) +>input : Symbol(input, Decl(contextuallyTypedParametersWithInitializers.ts, 3, 61)) +>T : Symbol(T, Decl(contextuallyTypedParametersWithInitializers.ts, 3, 21)) +>T : Symbol(T, Decl(contextuallyTypedParametersWithInitializers.ts, 3, 21)) + +declare function id5 any>(input: T): T; +>id5 : Symbol(id5, Decl(contextuallyTypedParametersWithInitializers.ts, 3, 74)) +>T : Symbol(T, Decl(contextuallyTypedParametersWithInitializers.ts, 4, 21)) +>x : Symbol(x, Decl(contextuallyTypedParametersWithInitializers.ts, 4, 32)) +>input : Symbol(input, Decl(contextuallyTypedParametersWithInitializers.ts, 4, 52)) +>T : Symbol(T, Decl(contextuallyTypedParametersWithInitializers.ts, 4, 21)) +>T : Symbol(T, Decl(contextuallyTypedParametersWithInitializers.ts, 4, 21)) + +const f10 = function ({ foo = 42 }) { return foo }; +>f10 : Symbol(f10, Decl(contextuallyTypedParametersWithInitializers.ts, 6, 5)) +>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 6, 23)) +>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 6, 23)) + +const f11 = id1(function ({ foo = 42 }) { return foo }); // Implicit any error +>f11 : Symbol(f11, Decl(contextuallyTypedParametersWithInitializers.ts, 7, 5)) +>id1 : Symbol(id1, Decl(contextuallyTypedParametersWithInitializers.ts, 0, 0)) +>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 7, 27)) +>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 7, 27)) + +const f12 = id2(function ({ foo = 42 }) { return foo }); +>f12 : Symbol(f12, Decl(contextuallyTypedParametersWithInitializers.ts, 8, 5)) +>id2 : Symbol(id2, Decl(contextuallyTypedParametersWithInitializers.ts, 0, 37)) +>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 8, 27)) +>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 8, 27)) + +const f13 = id3(function ({ foo = 42 }) { return foo }); +>f13 : Symbol(f13, Decl(contextuallyTypedParametersWithInitializers.ts, 9, 5)) +>id3 : Symbol(id3, Decl(contextuallyTypedParametersWithInitializers.ts, 1, 61)) +>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 9, 27)) +>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 9, 27)) + +const f14 = id4(function ({ foo = 42 }) { return foo }); +>f14 : Symbol(f14, Decl(contextuallyTypedParametersWithInitializers.ts, 10, 5)) +>id4 : Symbol(id4, Decl(contextuallyTypedParametersWithInitializers.ts, 2, 70)) +>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 10, 27)) +>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 10, 27)) + +const f20 = function (foo = 42) { return foo }; +>f20 : Symbol(f20, Decl(contextuallyTypedParametersWithInitializers.ts, 12, 5)) +>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 12, 22)) +>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 12, 22)) + +const f21 = id1(function (foo = 42) { return foo }); // Implicit any error +>f21 : Symbol(f21, Decl(contextuallyTypedParametersWithInitializers.ts, 13, 5)) +>id1 : Symbol(id1, Decl(contextuallyTypedParametersWithInitializers.ts, 0, 0)) +>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 13, 26)) +>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 13, 26)) + +const f22 = id2(function (foo = 42) { return foo }); +>f22 : Symbol(f22, Decl(contextuallyTypedParametersWithInitializers.ts, 14, 5)) +>id2 : Symbol(id2, Decl(contextuallyTypedParametersWithInitializers.ts, 0, 37)) +>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 14, 26)) +>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 14, 26)) + +const f25 = id5(function (foo = 42) { return foo }); +>f25 : Symbol(f25, Decl(contextuallyTypedParametersWithInitializers.ts, 15, 5)) +>id5 : Symbol(id5, Decl(contextuallyTypedParametersWithInitializers.ts, 3, 74)) +>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 15, 26)) +>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 15, 26)) + +// Repro from #28816 + +function id(input: T): T { return input } +>id : Symbol(id, Decl(contextuallyTypedParametersWithInitializers.ts, 15, 52)) +>T : Symbol(T, Decl(contextuallyTypedParametersWithInitializers.ts, 19, 12)) +>input : Symbol(input, Decl(contextuallyTypedParametersWithInitializers.ts, 19, 15)) +>T : Symbol(T, Decl(contextuallyTypedParametersWithInitializers.ts, 19, 12)) +>T : Symbol(T, Decl(contextuallyTypedParametersWithInitializers.ts, 19, 12)) +>input : Symbol(input, Decl(contextuallyTypedParametersWithInitializers.ts, 19, 15)) + +function getFoo ({ foo = 42 }) { +>getFoo : Symbol(getFoo, Decl(contextuallyTypedParametersWithInitializers.ts, 19, 44)) +>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 21, 18)) + + return foo; +>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 21, 18)) +} + +const newGetFoo = id(getFoo); +>newGetFoo : Symbol(newGetFoo, Decl(contextuallyTypedParametersWithInitializers.ts, 25, 5)) +>id : Symbol(id, Decl(contextuallyTypedParametersWithInitializers.ts, 15, 52)) +>getFoo : Symbol(getFoo, Decl(contextuallyTypedParametersWithInitializers.ts, 19, 44)) + +const newGetFoo2 = id(function getFoo ({ foo = 42 }) { +>newGetFoo2 : Symbol(newGetFoo2, Decl(contextuallyTypedParametersWithInitializers.ts, 26, 5)) +>id : Symbol(id, Decl(contextuallyTypedParametersWithInitializers.ts, 15, 52)) +>getFoo : Symbol(getFoo, Decl(contextuallyTypedParametersWithInitializers.ts, 26, 22)) +>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 26, 40)) + + return foo; +>foo : Symbol(foo, Decl(contextuallyTypedParametersWithInitializers.ts, 26, 40)) + +}); + diff --git a/tests/baselines/reference/contextuallyTypedParametersWithInitializers.types b/tests/baselines/reference/contextuallyTypedParametersWithInitializers.types new file mode 100644 index 0000000000000..3824b16ae62b4 --- /dev/null +++ b/tests/baselines/reference/contextuallyTypedParametersWithInitializers.types @@ -0,0 +1,140 @@ +=== tests/cases/compiler/contextuallyTypedParametersWithInitializers.ts === +declare function id1(input: T): T; +>id1 : (input: T) => T +>input : T + +declare function id2 any>(input: T): T; +>id2 : any>(input: T) => T +>x : any +>input : T + +declare function id3 any>(input: T): T; +>id3 : any>(input: T) => T +>x : { foo: any; } +>foo : any +>input : T + +declare function id4 any>(input: T): T; +>id4 : any>(input: T) => T +>x : { foo?: number | undefined; } +>foo : number | undefined +>input : T + +declare function id5 any>(input: T): T; +>id5 : any>(input: T) => T +>x : number | undefined +>input : T + +const f10 = function ({ foo = 42 }) { return foo }; +>f10 : ({ foo }: { foo?: number | undefined; }) => number +>function ({ foo = 42 }) { return foo } : ({ foo }: { foo?: number | undefined; }) => number +>foo : number +>42 : 42 +>foo : number + +const f11 = id1(function ({ foo = 42 }) { return foo }); // Implicit any error +>f11 : ({ foo }: any) => any +>id1(function ({ foo = 42 }) { return foo }) : ({ foo }: any) => any +>id1 : (input: T) => T +>function ({ foo = 42 }) { return foo } : ({ foo }: any) => any +>foo : any +>42 : 42 +>foo : any + +const f12 = id2(function ({ foo = 42 }) { return foo }); +>f12 : ({ foo }: any) => any +>id2(function ({ foo = 42 }) { return foo }) : ({ foo }: any) => any +>id2 : any>(input: T) => T +>function ({ foo = 42 }) { return foo } : ({ foo }: any) => any +>foo : any +>42 : 42 +>foo : any + +const f13 = id3(function ({ foo = 42 }) { return foo }); +>f13 : ({ foo }: { foo: any; }) => any +>id3(function ({ foo = 42 }) { return foo }) : ({ foo }: { foo: any; }) => any +>id3 : any>(input: T) => T +>function ({ foo = 42 }) { return foo } : ({ foo }: { foo: any; }) => any +>foo : any +>42 : 42 +>foo : any + +const f14 = id4(function ({ foo = 42 }) { return foo }); +>f14 : ({ foo }: { foo?: number | undefined; }) => number +>id4(function ({ foo = 42 }) { return foo }) : ({ foo }: { foo?: number | undefined; }) => number +>id4 : any>(input: T) => T +>function ({ foo = 42 }) { return foo } : ({ foo }: { foo?: number | undefined; }) => number +>foo : number +>42 : 42 +>foo : number + +const f20 = function (foo = 42) { return foo }; +>f20 : (foo?: number) => number +>function (foo = 42) { return foo } : (foo?: number) => number +>foo : number +>42 : 42 +>foo : number + +const f21 = id1(function (foo = 42) { return foo }); // Implicit any error +>f21 : (foo?: any) => any +>id1(function (foo = 42) { return foo }) : (foo?: any) => any +>id1 : (input: T) => T +>function (foo = 42) { return foo } : (foo?: any) => any +>foo : any +>42 : 42 +>foo : any + +const f22 = id2(function (foo = 42) { return foo }); +>f22 : (foo?: any) => any +>id2(function (foo = 42) { return foo }) : (foo?: any) => any +>id2 : any>(input: T) => T +>function (foo = 42) { return foo } : (foo?: any) => any +>foo : any +>42 : 42 +>foo : any + +const f25 = id5(function (foo = 42) { return foo }); +>f25 : (foo?: number | undefined) => number +>id5(function (foo = 42) { return foo }) : (foo?: number | undefined) => number +>id5 : any>(input: T) => T +>function (foo = 42) { return foo } : (foo?: number | undefined) => number +>foo : number | undefined +>42 : 42 +>foo : number + +// Repro from #28816 + +function id(input: T): T { return input } +>id : (input: T) => T +>input : T +>input : T + +function getFoo ({ foo = 42 }) { +>getFoo : ({ foo }: { foo?: number | undefined; }) => number +>foo : number +>42 : 42 + + return foo; +>foo : number +} + +const newGetFoo = id(getFoo); +>newGetFoo : ({ foo }: { foo?: number | undefined; }) => number +>id(getFoo) : ({ foo }: { foo?: number | undefined; }) => number +>id : (input: T) => T +>getFoo : ({ foo }: { foo?: number | undefined; }) => number + +const newGetFoo2 = id(function getFoo ({ foo = 42 }) { +>newGetFoo2 : ({ foo }: any) => any +>id(function getFoo ({ foo = 42 }) { return foo;}) : ({ foo }: any) => any +>id : (input: T) => T +>function getFoo ({ foo = 42 }) { return foo;} : ({ foo }: any) => any +>getFoo : ({ foo }: any) => any +>foo : any +>42 : 42 + + return foo; +>foo : any + +}); + diff --git a/tests/baselines/reference/fatarrowfunctionsErrors.types b/tests/baselines/reference/fatarrowfunctionsErrors.types index 4a493734e09aa..36b123e338af3 100644 --- a/tests/baselines/reference/fatarrowfunctionsErrors.types +++ b/tests/baselines/reference/fatarrowfunctionsErrors.types @@ -25,10 +25,10 @@ foo((x?)=>{return x;}) foo((x=0)=>{return x;}) >foo((x=0)=>{return x;}) : any >foo : any ->(x=0)=>{return x;} : (x?: number) => number ->x : number +>(x=0)=>{return x;} : (x?: any) => any +>x : any >0 : 0 ->x : number +>x : any var y = x:number => x*x; >y : any diff --git a/tests/baselines/reference/fatarrowfunctionsOptionalArgs.types b/tests/baselines/reference/fatarrowfunctionsOptionalArgs.types index e9ae9488b91cd..ed7438dd6a057 100644 --- a/tests/baselines/reference/fatarrowfunctionsOptionalArgs.types +++ b/tests/baselines/reference/fatarrowfunctionsOptionalArgs.types @@ -653,8 +653,8 @@ foo( >116 : 116 (a = 0) => 117, ->(a = 0) => 117 : (a?: number) => number ->a : number +>(a = 0) => 117 : (a?: any) => number +>a : any >0 : 0 >117 : 117 @@ -670,9 +670,9 @@ foo( >119 : 119 (a, b? = 0, ...c: number[]) => 120, ->(a, b? = 0, ...c: number[]) => 120 : (a: any, b?: number, ...c: number[]) => number +>(a, b? = 0, ...c: number[]) => 120 : (a: any, b?: any, ...c: number[]) => number >a : any ->b : number +>b : any >0 : 0 >c : number[] >120 : 120 diff --git a/tests/baselines/reference/fatarrowfunctionsOptionalArgsErrors4.types b/tests/baselines/reference/fatarrowfunctionsOptionalArgsErrors4.types index 18860e274ca20..7496677a194b0 100644 --- a/tests/baselines/reference/fatarrowfunctionsOptionalArgsErrors4.types +++ b/tests/baselines/reference/fatarrowfunctionsOptionalArgsErrors4.types @@ -88,8 +88,8 @@ >116 : 116 (a = 0) => 117, ->(a = 0) => 117 : (a?: number) => number ->a : number +>(a = 0) => 117 : (a?: any) => number +>a : any >0 : 0 >117 : 117 @@ -105,9 +105,9 @@ >119 : 119 (a, b? = 0, ...c: number[]) => 120, ->(a, b? = 0, ...c: number[]) => 120 : (a: any, b?: number, ...c: number[]) => number +>(a, b? = 0, ...c: number[]) => 120 : (a: any, b?: any, ...c: number[]) => number >a : any ->b : number +>b : any >0 : 0 >c : number[] >120 : 120 diff --git a/tests/cases/compiler/contextuallyTypedParametersWithInitializers.ts b/tests/cases/compiler/contextuallyTypedParametersWithInitializers.ts new file mode 100644 index 0000000000000..e68be5b7bfd8a --- /dev/null +++ b/tests/cases/compiler/contextuallyTypedParametersWithInitializers.ts @@ -0,0 +1,32 @@ +// @strict: true +// @declaration: true + +declare function id1(input: T): T; +declare function id2 any>(input: T): T; +declare function id3 any>(input: T): T; +declare function id4 any>(input: T): T; +declare function id5 any>(input: T): T; + +const f10 = function ({ foo = 42 }) { return foo }; +const f11 = id1(function ({ foo = 42 }) { return foo }); // Implicit any error +const f12 = id2(function ({ foo = 42 }) { return foo }); +const f13 = id3(function ({ foo = 42 }) { return foo }); +const f14 = id4(function ({ foo = 42 }) { return foo }); + +const f20 = function (foo = 42) { return foo }; +const f21 = id1(function (foo = 42) { return foo }); // Implicit any error +const f22 = id2(function (foo = 42) { return foo }); +const f25 = id5(function (foo = 42) { return foo }); + +// Repro from #28816 + +function id(input: T): T { return input } + +function getFoo ({ foo = 42 }) { + return foo; +} + +const newGetFoo = id(getFoo); +const newGetFoo2 = id(function getFoo ({ foo = 42 }) { + return foo; +});