Merge pull request #29576 from Microsoft/fixContextuallyTypedParameters

Fix inference for contextually typed parameters with initializers
This commit is contained in:
Anders Hejlsberg 2019-01-30 15:51:29 -08:00 committed by GitHub
commit eb513a2035
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 489 additions and 30 deletions

View file

@ -4866,17 +4866,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
@ -4962,6 +4953,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(<Expression>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
@ -5045,8 +5042,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);
}
@ -5057,8 +5055,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);
}
@ -5695,17 +5694,21 @@ namespace ts {
}
function reportCircularityError(symbol: Symbol) {
const declaration = <VariableLikeDeclaration>symbol.valueDeclaration;
// Check if variable has type annotation that circularly references the variable itself
if (getEffectiveTypeAnnotationNode(<VariableLikeDeclaration>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 || (<HasInitializer>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;
}
@ -25680,7 +25683,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);

View file

@ -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<T>(input: T): T;
declare function id2<T extends (x: any) => any>(input: T): T;
declare function id3<T extends (x: { foo: any }) => any>(input: T): T;
declare function id4<T extends (x: { foo?: number }) => any>(input: T): T;
declare function id5<T extends (x?: number) => 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<T>(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;
});

View file

@ -0,0 +1,114 @@
//// [contextuallyTypedParametersWithInitializers.ts]
declare function id1<T>(input: T): T;
declare function id2<T extends (x: any) => any>(input: T): T;
declare function id3<T extends (x: { foo: any }) => any>(input: T): T;
declare function id4<T extends (x: { foo?: number }) => any>(input: T): T;
declare function id5<T extends (x?: number) => 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<T>(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<T>(input: T): T;
declare function id2<T extends (x: any) => any>(input: T): T;
declare function id3<T extends (x: {
foo: any;
}) => any>(input: T): T;
declare function id4<T extends (x: {
foo?: number;
}) => any>(input: T): T;
declare function id5<T extends (x?: number) => 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<T>(input: T): T;
declare function getFoo({ foo }: {
foo?: number | undefined;
}): number;
declare const newGetFoo: typeof getFoo;
declare const newGetFoo2: ({ foo }: any) => any;

View file

@ -0,0 +1,128 @@
=== tests/cases/compiler/contextuallyTypedParametersWithInitializers.ts ===
declare function id1<T>(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<T extends (x: any) => 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<T extends (x: { foo: any }) => 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<T extends (x: { foo?: number }) => 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<T extends (x?: number) => 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<T>(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))
});

View file

@ -0,0 +1,140 @@
=== tests/cases/compiler/contextuallyTypedParametersWithInitializers.ts ===
declare function id1<T>(input: T): T;
>id1 : <T>(input: T) => T
>input : T
declare function id2<T extends (x: any) => any>(input: T): T;
>id2 : <T extends (x: any) => any>(input: T) => T
>x : any
>input : T
declare function id3<T extends (x: { foo: any }) => any>(input: T): T;
>id3 : <T extends (x: { foo: any; }) => any>(input: T) => T
>x : { foo: any; }
>foo : any
>input : T
declare function id4<T extends (x: { foo?: number }) => any>(input: T): T;
>id4 : <T extends (x: { foo?: number | undefined; }) => any>(input: T) => T
>x : { foo?: number | undefined; }
>foo : number | undefined
>input : T
declare function id5<T extends (x?: number) => any>(input: T): T;
>id5 : <T extends (x?: number | undefined) => 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 : <T>(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 : <T extends (x: any) => 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 : <T extends (x: { foo: any; }) => 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 : <T extends (x: { foo?: number | undefined; }) => 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 : <T>(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 : <T extends (x: any) => 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 : <T extends (x?: number | undefined) => 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<T>(input: T): T { return input }
>id : <T>(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 : <T>(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 : <T>(input: T) => T
>function getFoo ({ foo = 42 }) { return foo;} : ({ foo }: any) => any
>getFoo : ({ foo }: any) => any
>foo : any
>42 : 42
return foo;
>foo : any
});

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,32 @@
// @strict: true
// @declaration: true
declare function id1<T>(input: T): T;
declare function id2<T extends (x: any) => any>(input: T): T;
declare function id3<T extends (x: { foo: any }) => any>(input: T): T;
declare function id4<T extends (x: { foo?: number }) => any>(input: T): T;
declare function id5<T extends (x?: number) => 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<T>(input: T): T { return input }
function getFoo ({ foo = 42 }) {
return foo;
}
const newGetFoo = id(getFoo);
const newGetFoo2 = id(function getFoo ({ foo = 42 }) {
return foo;
});