From b44bfaaaa8edf88e83779e1f0399a8518dfff389 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 28 Feb 2019 06:15:26 -0800 Subject: [PATCH 01/19] Convert CheckMode to a flags style enum --- src/compiler/checker.ts | 43 ++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 002fdecc0cd39..440dacc759733 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -681,10 +681,10 @@ namespace ts { } const enum CheckMode { - Normal = 0, // Normal type checking - SkipContextSensitive = 1, // Skip context sensitive function expressions - Inferential = 2, // Inferential typing - Contextual = 3, // Normal type checking informed by a contextual type, therefore not cacheable + Normal = 0, // Normal type checking + Contextual = 1 << 0, // Explicitly assigned contextual type, therefore not cacheable + Inferential = 1 << 1, // Inferential typing + SkipContextSensitive = 1 << 2, // Skip context sensitive function expressions } const enum CallbackCheck { @@ -19985,10 +19985,9 @@ namespace ts { function inferJsxTypeArguments(node: JsxOpeningLikeElement, signature: Signature, excludeArgument: ReadonlyArray | undefined, context: InferenceContext): Type[] { const paramType = getEffectiveFirstArgumentForJsxSignature(signature, node); - - const checkAttrType = checkExpressionWithContextualType(node.attributes, paramType, excludeArgument && excludeArgument[0] !== undefined ? identityMapper : context); + const checkMode = excludeArgument && excludeArgument[0] ? CheckMode.SkipContextSensitive : 0; + const checkAttrType = checkExpressionWithContextualType(node.attributes, paramType, context, checkMode); inferTypes(context.inferences, checkAttrType, paramType); - return getInferredTypes(context); } @@ -20054,8 +20053,8 @@ namespace ts { const paramType = getTypeAtPosition(signature, i); // For context sensitive arguments we pass the identityMapper, which is a signal to treat all // context sensitive function expressions as wildcards - const mapper = excludeArgument && excludeArgument[i] !== undefined ? identityMapper : context; - const argType = checkExpressionWithContextualType(arg, paramType, mapper); + const checkMode = excludeArgument && excludeArgument[i] ? CheckMode.SkipContextSensitive : 0; + const argType = checkExpressionWithContextualType(arg, paramType, context, checkMode); inferTypes(context.inferences, argType, paramType); } } @@ -20083,7 +20082,7 @@ namespace ts { // and the argument are ...x forms. return arg.kind === SyntaxKind.SyntheticExpression ? createArrayType((arg).type) : - getArrayifiedType(checkExpressionWithContextualType((arg).expression, restType, context)); + getArrayifiedType(checkExpressionWithContextualType((arg).expression, restType, context, CheckMode.Normal)); } } const contextualType = getIndexTypeOfType(restType, IndexKind.Number) || anyType; @@ -20091,7 +20090,7 @@ namespace ts { const types = []; let spreadIndex = -1; for (let i = index; i < argCount; i++) { - const argType = checkExpressionWithContextualType(args[i], contextualType, context); + const argType = checkExpressionWithContextualType(args[i], contextualType, context, CheckMode.Normal); if (spreadIndex < 0 && isSpreadArgument(args[i])) { spreadIndex = i - index; } @@ -20156,7 +20155,8 @@ namespace ts { // However "context" and "updater" are implicit and can't be specify by users. Only the first parameter, props, // can be specified by users through attributes property. const paramType = getEffectiveFirstArgumentForJsxSignature(signature, node); - const attributesType = checkExpressionWithContextualType(node.attributes, paramType, excludeArgument && excludeArgument[0] ? identityMapper : undefined); + const checkMode = excludeArgument && excludeArgument[0] ? CheckMode.SkipContextSensitive : 0; + const attributesType = checkExpressionWithContextualType(node.attributes, paramType, undefined, checkMode); return checkTypeRelatedToAndOptionallyElaborate(attributesType, paramType, relation, reportErrors ? node.tagName : undefined, node.attributes); } @@ -20190,7 +20190,8 @@ namespace ts { const arg = args[i]; if (arg.kind !== SyntaxKind.OmittedExpression) { const paramType = getTypeAtPosition(signature, i); - const argType = checkExpressionWithContextualType(arg, paramType, excludeArgument && excludeArgument[i] ? identityMapper : undefined); + const checkMode = excludeArgument && excludeArgument[i] ? CheckMode.SkipContextSensitive : 0; + const argType = checkExpressionWithContextualType(arg, paramType, undefined, checkMode); // If one or more arguments are still excluded (as indicated by a non-null excludeArgument parameter), // we obtain the regular type of any object literal arguments because we may not have inferred complete // parameter types yet and therefore excess property checks may yield false positives (see #17041). @@ -21145,7 +21146,7 @@ namespace ts { if (isJsxIntrinsicIdentifier(node.tagName)) { const result = getIntrinsicAttributesTypeFromJsxOpeningLikeElement(node); const fakeSignature = createSignatureForJSXIntrinsic(node, result); - checkTypeAssignableToAndOptionallyElaborate(checkExpressionWithContextualType(node.attributes, getEffectiveFirstArgumentForJsxSignature(fakeSignature, node), /*mapper*/ undefined), result, node.tagName, node.attributes); + checkTypeAssignableToAndOptionallyElaborate(checkExpressionWithContextualType(node.attributes, getEffectiveFirstArgumentForJsxSignature(fakeSignature, node), /*mapper*/ undefined, CheckMode.Normal), result, node.tagName, node.attributes); return fakeSignature; } const exprTypes = checkExpression(node.tagName); @@ -22086,7 +22087,7 @@ namespace ts { checkNodeDeferred(node); // The identityMapper object is used to indicate that function expressions are wildcards - if (checkMode === CheckMode.SkipContextSensitive && isContextSensitive(node)) { + if (checkMode && checkMode & CheckMode.SkipContextSensitive && isContextSensitive(node)) { // Skip parameters, return signature with return type that retains noncontextual parts so inferences can still be drawn in an early stage if (!getEffectiveReturnTypeNode(node) && hasContextSensitiveReturnExpression(node)) { const links = getNodeLinks(node); @@ -22126,7 +22127,7 @@ namespace ts { const signature = getSignaturesOfType(type, SignatureKind.Call)[0]; if (isContextSensitive(node)) { const contextualMapper = getContextualMapper(node); - if (checkMode === CheckMode.Inferential) { + if (checkMode && checkMode & CheckMode.Inferential) { inferFromAnnotatedParameters(signature, contextualSignature, contextualMapper); } const instantiatedContextualSignature = contextualMapper === identityMapper ? @@ -23137,15 +23138,13 @@ namespace ts { return node; } - function checkExpressionWithContextualType(node: Expression, contextualType: Type, contextualMapper: TypeMapper | undefined): Type { + function checkExpressionWithContextualType(node: Expression, contextualType: Type, contextualMapper: TypeMapper | undefined, checkMode: CheckMode): Type { const context = getContextNode(node); const saveContextualType = context.contextualType; const saveContextualMapper = context.contextualMapper; context.contextualType = contextualType; context.contextualMapper = contextualMapper; - const checkMode = contextualMapper === identityMapper ? CheckMode.SkipContextSensitive : - contextualMapper ? CheckMode.Inferential : CheckMode.Contextual; - const type = checkExpression(node, checkMode); + const type = checkExpression(node, checkMode | CheckMode.Contextual | (contextualMapper ? CheckMode.Inferential : 0)); // We strip literal freshness when an appropriate contextual type is present such that contextually typed // literals always preserve their literal types (otherwise they might widen during type inference). An alternative // here would be to not mark contextually typed literals as fresh in the first place. @@ -23159,7 +23158,7 @@ namespace ts { function checkExpressionCached(node: Expression, checkMode?: CheckMode): Type { const links = getNodeLinks(node); if (!links.resolvedType) { - if (checkMode) { + if (checkMode && checkMode !== CheckMode.Normal) { return checkExpression(node, checkMode); } // When computing a type that we're going to cache, we need to ignore any ongoing control flow @@ -23267,7 +23266,7 @@ namespace ts { } function instantiateTypeWithSingleGenericCallSignature(node: Expression | MethodDeclaration | QualifiedName, type: Type, checkMode?: CheckMode) { - if (checkMode === CheckMode.Inferential) { + if (checkMode && checkMode & CheckMode.Inferential) { const signature = getSingleCallSignature(type); if (signature && signature.typeParameters) { const contextualType = getApparentTypeOfContextualType(node); From 23473e021b0006f37d0d2e8f9c5c9de182641cd6 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 28 Feb 2019 17:14:00 -0800 Subject: [PATCH 02/19] Skip generic functions along with context sensitive arguments --- src/compiler/checker.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 440dacc759733..e4fbbd6a9a654 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -685,6 +685,7 @@ namespace ts { Contextual = 1 << 0, // Explicitly assigned contextual type, therefore not cacheable Inferential = 1 << 1, // Inferential typing SkipContextSensitive = 1 << 2, // Skip context sensitive function expressions + SkipGenericFunctions = 1 << 3, // Skip single signature generic functions } const enum CallbackCheck { @@ -20053,7 +20054,8 @@ namespace ts { const paramType = getTypeAtPosition(signature, i); // For context sensitive arguments we pass the identityMapper, which is a signal to treat all // context sensitive function expressions as wildcards - const checkMode = excludeArgument && excludeArgument[i] ? CheckMode.SkipContextSensitive : 0; + const checkMode = (excludeArgument && excludeArgument[i] ? CheckMode.SkipContextSensitive : 0) | + (excludeArgument ? CheckMode.SkipGenericFunctions : 0); const argType = checkExpressionWithContextualType(arg, paramType, context, checkMode); inferTypes(context.inferences, argType, paramType); } @@ -20190,7 +20192,8 @@ namespace ts { const arg = args[i]; if (arg.kind !== SyntaxKind.OmittedExpression) { const paramType = getTypeAtPosition(signature, i); - const checkMode = excludeArgument && excludeArgument[i] ? CheckMode.SkipContextSensitive : 0; + const checkMode = (excludeArgument && excludeArgument[i] ? CheckMode.SkipContextSensitive : 0) | + (excludeArgument ? CheckMode.SkipGenericFunctions : 0); const argType = checkExpressionWithContextualType(arg, paramType, undefined, checkMode); // If one or more arguments are still excluded (as indicated by a non-null excludeArgument parameter), // we obtain the regular type of any object literal arguments because we may not have inferred complete @@ -23266,9 +23269,12 @@ namespace ts { } function instantiateTypeWithSingleGenericCallSignature(node: Expression | MethodDeclaration | QualifiedName, type: Type, checkMode?: CheckMode) { - if (checkMode && checkMode & CheckMode.Inferential) { + if (checkMode && checkMode & (CheckMode.Inferential | CheckMode.SkipGenericFunctions)) { const signature = getSingleCallSignature(type); if (signature && signature.typeParameters) { + if (checkMode & CheckMode.SkipGenericFunctions) { + return anyFunctionType; + } const contextualType = getApparentTypeOfContextualType(node); if (contextualType) { const contextualSignature = getSingleCallSignature(getNonNullableType(contextualType)); @@ -23278,7 +23284,6 @@ namespace ts { } } } - return type; } From 35ebbece49320b48df5a0cb048a08a34256718e0 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 1 Mar 2019 09:12:24 -0800 Subject: [PATCH 03/19] Minor fixes --- src/compiler/checker.ts | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0d9363dc1d816..bce50c821a590 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -20036,7 +20036,12 @@ namespace ts { // Instantiate a generic signature in the context of a non-generic signature (section 3.8.5 in TypeScript spec) function instantiateSignatureInContextOf(signature: Signature, contextualSignature: Signature, contextualMapper?: TypeMapper, compareTypes?: TypeComparer): Signature { const context = createInferenceContext(signature.typeParameters!, signature, InferenceFlags.None, compareTypes); - const sourceSignature = contextualMapper ? instantiateSignature(contextualSignature, contextualMapper) : contextualSignature; + // We clone the contextualMapper to avoid fixing. For example, when the source signature is (x: T) => T[] and + // the contextual signature is (...args: A) => B, we want to infer the element type of A's constraint (say 'any') + // for T but leave it possible to later infer '[any]' back to A. + const restType = getEffectiveRestType(contextualSignature); + const mapper = contextualMapper && restType && restType.flags & TypeFlags.TypeParameter ? cloneTypeMapper(contextualMapper) : contextualMapper; + const sourceSignature = mapper ? instantiateSignature(contextualSignature, mapper) : contextualSignature; forEachMatchingParameterType(sourceSignature, signature, (source, target) => { // Type parameters from outer context referenced by source type are fixed by instantiation of the source type inferTypes(context.inferences, source, target); @@ -20221,7 +20226,7 @@ namespace ts { // can be specified by users through attributes property. const paramType = getEffectiveFirstArgumentForJsxSignature(signature, node); const checkMode = excludeArgument && excludeArgument[0] ? CheckMode.SkipContextSensitive : 0; - const attributesType = checkExpressionWithContextualType(node.attributes, paramType, undefined, checkMode); + const attributesType = checkExpressionWithContextualType(node.attributes, paramType, /*contextualMapper*/ undefined, checkMode); return checkTypeRelatedToAndOptionallyElaborate(attributesType, paramType, relation, reportErrors ? node.tagName : undefined, node.attributes); } @@ -20257,7 +20262,7 @@ namespace ts { const paramType = getTypeAtPosition(signature, i); const checkMode = (excludeArgument && excludeArgument[i] ? CheckMode.SkipContextSensitive : 0) | (excludeArgument ? CheckMode.SkipGenericFunctions : 0); - const argType = checkExpressionWithContextualType(arg, paramType, undefined, checkMode); + const argType = checkExpressionWithContextualType(arg, paramType, /*contextualMapper*/ undefined, checkMode); // If one or more arguments are still excluded (as indicated by a non-null excludeArgument parameter), // we obtain the regular type of any object literal arguments because we may not have inferred complete // parameter types yet and therefore excess property checks may yield false positives (see #17041). @@ -21874,7 +21879,7 @@ namespace ts { const functionFlags = getFunctionFlags(func); let type: Type; if (func.body.kind !== SyntaxKind.Block) { - type = checkExpressionCached(func.body, checkMode); + type = checkExpressionCached(func.body, checkMode && checkMode & ~CheckMode.SkipGenericFunctions); if (functionFlags & FunctionFlags.Async) { // From within an async function you can return either a non-promise value or a promise. Any // Promise/A+ compatible implementation will always assimilate any foreign promise, so the @@ -22064,7 +22069,7 @@ namespace ts { forEachReturnStatement(func.body, returnStatement => { const expr = returnStatement.expression; if (expr) { - let type = checkExpressionCached(expr, checkMode); + let type = checkExpressionCached(expr, checkMode && checkMode && checkMode & ~CheckMode.SkipGenericFunctions); if (functionFlags & FunctionFlags.Async) { // From within an async function you can return either a non-promise value or a promise. Any // Promise/A+ compatible implementation will always assimilate any foreign promise, so the From 91f8fc60f1b0cc42c7842d71ee5fe7a0b2f37595 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 2 Mar 2019 10:34:23 -0800 Subject: [PATCH 04/19] Defer calls to generic functions returning generic functions --- src/compiler/checker.ts | 86 +++++++++++++++++++++++++---------------- 1 file changed, 53 insertions(+), 33 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index bce50c821a590..a8dccb072b1a5 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -228,9 +228,9 @@ namespace ts { isContextSensitive, getFullyQualifiedName, getResolvedSignature: (node, candidatesOutArray, agumentCount) => - getResolvedSignatureWorker(node, candidatesOutArray, agumentCount, /*isForSignatureHelp*/ false), + getResolvedSignatureWorker(node, candidatesOutArray, agumentCount, CheckMode.Normal), getResolvedSignatureForSignatureHelp: (node, candidatesOutArray, agumentCount) => - getResolvedSignatureWorker(node, candidatesOutArray, agumentCount, /*isForSignatureHelp*/ true), + getResolvedSignatureWorker(node, candidatesOutArray, agumentCount, CheckMode.IsForSignatureHelp), getConstantValue: nodeIn => { const node = getParseTreeNode(nodeIn, canHaveConstantValue); return node ? getConstantValue(node) : undefined; @@ -374,10 +374,10 @@ namespace ts { getLocalTypeParametersOfClassOrInterfaceOrTypeAlias, }; - function getResolvedSignatureWorker(nodeIn: CallLikeExpression, candidatesOutArray: Signature[] | undefined, argumentCount: number | undefined, isForSignatureHelp: boolean): Signature | undefined { + function getResolvedSignatureWorker(nodeIn: CallLikeExpression, candidatesOutArray: Signature[] | undefined, argumentCount: number | undefined, checkMode: CheckMode): Signature | undefined { const node = getParseTreeNode(nodeIn, isCallLikeExpression); apparentArgumentCount = argumentCount; - const res = node ? getResolvedSignature(node, candidatesOutArray, isForSignatureHelp) : undefined; + const res = node ? getResolvedSignature(node, candidatesOutArray, checkMode) : undefined; apparentArgumentCount = undefined; return res; } @@ -693,6 +693,7 @@ namespace ts { Inferential = 1 << 1, // Inferential typing SkipContextSensitive = 1 << 2, // Skip context sensitive function expressions SkipGenericFunctions = 1 << 3, // Skip single signature generic functions + IsForSignatureHelp = 1 << 4, // Call resolution for purposes of signature help } const enum CallbackCheck { @@ -20482,7 +20483,7 @@ namespace ts { return createDiagnosticForNodeArray(getSourceFileOfNode(node), typeArguments, Diagnostics.Expected_0_type_arguments_but_got_1, belowArgCount === -Infinity ? aboveArgCount : belowArgCount, argCount); } - function resolveCall(node: CallLikeExpression, signatures: ReadonlyArray, candidatesOutArray: Signature[] | undefined, isForSignatureHelp: boolean, fallbackError?: DiagnosticMessage): Signature { + function resolveCall(node: CallLikeExpression, signatures: ReadonlyArray, candidatesOutArray: Signature[] | undefined, checkMode: CheckMode, fallbackError?: DiagnosticMessage): Signature { const isTaggedTemplate = node.kind === SyntaxKind.TaggedTemplateExpression; const isDecorator = node.kind === SyntaxKind.Decorator; const isJsxOpeningOrSelfClosingElement = isJsxOpeningLikeElement(node); @@ -20555,7 +20556,7 @@ namespace ts { // If we are in signature help, a trailing comma indicates that we intend to provide another argument, // so we will only accept overloads with arity at least 1 higher than the current number of provided arguments. const signatureHelpTrailingComma = - isForSignatureHelp && node.kind === SyntaxKind.CallExpression && node.arguments.hasTrailingComma; + !!(checkMode & CheckMode.IsForSignatureHelp) && node.kind === SyntaxKind.CallExpression && node.arguments.hasTrailingComma; // Section 4.12.1: // if the candidate list contains one or more signatures for which the type of each argument @@ -20837,7 +20838,7 @@ namespace ts { return maxParamsIndex; } - function resolveCallExpression(node: CallExpression, candidatesOutArray: Signature[] | undefined, isForSignatureHelp: boolean): Signature { + function resolveCallExpression(node: CallExpression, candidatesOutArray: Signature[] | undefined, checkMode: CheckMode): Signature { if (node.expression.kind === SyntaxKind.SuperKeyword) { const superType = checkSuperExpression(node.expression); if (isTypeAny(superType)) { @@ -20852,7 +20853,7 @@ namespace ts { const baseTypeNode = getEffectiveBaseTypeNode(getContainingClass(node)!); if (baseTypeNode) { const baseConstructors = getInstantiatedConstructorsForTypeArguments(superType, baseTypeNode.typeArguments, baseTypeNode); - return resolveCall(node, baseConstructors, candidatesOutArray, isForSignatureHelp); + return resolveCall(node, baseConstructors, candidatesOutArray, checkMode); } } return resolveUntypedCall(node); @@ -20912,12 +20913,22 @@ namespace ts { } return resolveErrorCall(node); } + // If we are skipping generic functions (i.e. this call is an argument to another call for which context + // sensitive arguments are being deferred) and every call signature is generic and returns a function type, + // we return resolvingSignature here. This result will be propagated out and turned into anyFunctionType. + if (checkMode & CheckMode.SkipGenericFunctions && callSignatures.every(isGenericFunctionReturningFunction)) { + return resolvingSignature; + } // If the function is explicitly marked with `@class`, then it must be constructed. if (callSignatures.some(sig => isInJSFile(sig.declaration) && !!getJSDocClassTag(sig.declaration!))) { error(node, Diagnostics.Value_of_type_0_is_not_callable_Did_you_mean_to_include_new, typeToString(funcType)); return resolveErrorCall(node); } - return resolveCall(node, callSignatures, candidatesOutArray, isForSignatureHelp); + return resolveCall(node, callSignatures, candidatesOutArray, checkMode); + } + + function isGenericFunctionReturningFunction(signature: Signature) { + return !!(signature.typeParameters && getSingleCallSignature(getReturnTypeOfSignature(signature))); } /** @@ -20931,7 +20942,7 @@ namespace ts { !numCallSignatures && !numConstructSignatures && !(apparentFuncType.flags & (TypeFlags.Union | TypeFlags.Never)) && isTypeAssignableTo(funcType, globalFunctionType); } - function resolveNewExpression(node: NewExpression, candidatesOutArray: Signature[] | undefined, isForSignatureHelp: boolean): Signature { + function resolveNewExpression(node: NewExpression, candidatesOutArray: Signature[] | undefined, checkMode: CheckMode): Signature { if (node.arguments && languageVersion < ScriptTarget.ES5) { const spreadIndex = getSpreadArgumentIndex(node.arguments); if (spreadIndex >= 0) { @@ -20984,7 +20995,7 @@ namespace ts { return resolveErrorCall(node); } - return resolveCall(node, constructSignatures, candidatesOutArray, isForSignatureHelp); + return resolveCall(node, constructSignatures, candidatesOutArray, checkMode); } // If expressionType's apparent type is an object type with no construct signatures but @@ -20993,7 +21004,7 @@ namespace ts { // operation is Any. It is an error to have a Void this type. const callSignatures = getSignaturesOfType(expressionType, SignatureKind.Call); if (callSignatures.length) { - const signature = resolveCall(node, callSignatures, candidatesOutArray, isForSignatureHelp); + const signature = resolveCall(node, callSignatures, candidatesOutArray, checkMode); if (!noImplicitAny) { if (signature.declaration && !isJSConstructor(signature.declaration) && getReturnTypeOfSignature(signature) !== voidType) { error(node, Diagnostics.Only_a_void_function_can_be_called_with_the_new_keyword); @@ -21103,7 +21114,7 @@ namespace ts { } } - function resolveTaggedTemplateExpression(node: TaggedTemplateExpression, candidatesOutArray: Signature[] | undefined, isForSignatureHelp: boolean): Signature { + function resolveTaggedTemplateExpression(node: TaggedTemplateExpression, candidatesOutArray: Signature[] | undefined, checkMode: CheckMode): Signature { const tagType = checkExpression(node.tag); const apparentType = getApparentType(tagType); @@ -21124,7 +21135,7 @@ namespace ts { return resolveErrorCall(node); } - return resolveCall(node, callSignatures, candidatesOutArray, isForSignatureHelp); + return resolveCall(node, callSignatures, candidatesOutArray, checkMode); } /** @@ -21155,7 +21166,7 @@ namespace ts { /** * Resolves a decorator as if it were a call expression. */ - function resolveDecorator(node: Decorator, candidatesOutArray: Signature[] | undefined, isForSignatureHelp: boolean): Signature { + function resolveDecorator(node: Decorator, candidatesOutArray: Signature[] | undefined, checkMode: CheckMode): Signature { const funcType = checkExpression(node.expression); const apparentType = getApparentType(funcType); if (apparentType === errorType) { @@ -21184,7 +21195,7 @@ namespace ts { return resolveErrorCall(node); } - return resolveCall(node, callSignatures, candidatesOutArray, isForSignatureHelp, headMessage); + return resolveCall(node, callSignatures, candidatesOutArray, checkMode, headMessage); } function createSignatureForJSXIntrinsic(node: JsxOpeningLikeElement, result: Type): Signature { @@ -21213,7 +21224,7 @@ namespace ts { ); } - function resolveJsxOpeningLikeElement(node: JsxOpeningLikeElement, candidatesOutArray: Signature[] | undefined, isForSignatureHelp: boolean): Signature { + function resolveJsxOpeningLikeElement(node: JsxOpeningLikeElement, candidatesOutArray: Signature[] | undefined, checkMode: CheckMode): Signature { if (isJsxIntrinsicIdentifier(node.tagName)) { const result = getIntrinsicAttributesTypeFromJsxOpeningLikeElement(node); const fakeSignature = createSignatureForJSXIntrinsic(node, result); @@ -21237,7 +21248,7 @@ namespace ts { return resolveErrorCall(node); } - return resolveCall(node, signatures, candidatesOutArray, isForSignatureHelp); + return resolveCall(node, signatures, candidatesOutArray, checkMode); } /** @@ -21252,19 +21263,19 @@ namespace ts { signature.parameters.length < getDecoratorArgumentCount(decorator, signature)); } - function resolveSignature(node: CallLikeExpression, candidatesOutArray: Signature[] | undefined, isForSignatureHelp: boolean): Signature { + function resolveSignature(node: CallLikeExpression, candidatesOutArray: Signature[] | undefined, checkMode: CheckMode): Signature { switch (node.kind) { case SyntaxKind.CallExpression: - return resolveCallExpression(node, candidatesOutArray, isForSignatureHelp); + return resolveCallExpression(node, candidatesOutArray, checkMode); case SyntaxKind.NewExpression: - return resolveNewExpression(node, candidatesOutArray, isForSignatureHelp); + return resolveNewExpression(node, candidatesOutArray, checkMode); case SyntaxKind.TaggedTemplateExpression: - return resolveTaggedTemplateExpression(node, candidatesOutArray, isForSignatureHelp); + return resolveTaggedTemplateExpression(node, candidatesOutArray, checkMode); case SyntaxKind.Decorator: - return resolveDecorator(node, candidatesOutArray, isForSignatureHelp); + return resolveDecorator(node, candidatesOutArray, checkMode); case SyntaxKind.JsxOpeningElement: case SyntaxKind.JsxSelfClosingElement: - return resolveJsxOpeningLikeElement(node, candidatesOutArray, isForSignatureHelp); + return resolveJsxOpeningLikeElement(node, candidatesOutArray, checkMode); } throw Debug.assertNever(node, "Branch in 'resolveSignature' should be unreachable."); } @@ -21276,7 +21287,7 @@ namespace ts { * the function will fill it up with appropriate candidate signatures * @return a signature of the call-like expression or undefined if one can't be found */ - function getResolvedSignature(node: CallLikeExpression, candidatesOutArray?: Signature[] | undefined, isForSignatureHelp = false): Signature { + function getResolvedSignature(node: CallLikeExpression, candidatesOutArray?: Signature[] | undefined, checkMode?: CheckMode): Signature { const links = getNodeLinks(node); // If getResolvedSignature has already been called, we will have cached the resolvedSignature. // However, it is possible that either candidatesOutArray was not passed in the first time, @@ -21287,11 +21298,15 @@ namespace ts { return cached; } links.resolvedSignature = resolvingSignature; - const result = resolveSignature(node, candidatesOutArray, isForSignatureHelp); - // If signature resolution originated in control flow type analysis (for example to compute the - // assigned type in a flow assignment) we don't cache the result as it may be based on temporary - // types from the control flow analysis. - links.resolvedSignature = flowLoopStart === flowLoopCount ? result : cached; + const result = resolveSignature(node, candidatesOutArray, checkMode || CheckMode.Normal); + // When CheckMode.SkipGenericFunctions is set we use resolvingSignature to indicate that call + // resolution should be deferred. + if (result !== resolvingSignature) { + // If signature resolution originated in control flow type analysis (for example to compute the + // assigned type in a flow assignment) we don't cache the result as it may be based on temporary + // types from the control flow analysis. + links.resolvedSignature = flowLoopStart === flowLoopCount ? result : cached; + } return result; } @@ -21375,10 +21390,15 @@ namespace ts { * @param node The call/new expression to be checked. * @returns On success, the expression's signature's return type. On failure, anyType. */ - function checkCallExpression(node: CallExpression | NewExpression): Type { + function checkCallExpression(node: CallExpression | NewExpression, checkMode?: CheckMode): Type { if (!checkGrammarTypeArguments(node, node.typeArguments)) checkGrammarArguments(node.arguments); - const signature = getResolvedSignature(node); + const signature = getResolvedSignature(node, /*candidatesOutArray*/ undefined, checkMode); + if (signature === resolvingSignature) { + // CheckMode.SkipGenericFunctions is enabled and this is a call to a generic function that + // returns a function type. We defer checking and return anyFunctionType. + return anyFunctionType; + } if (node.expression.kind === SyntaxKind.SuperKeyword) { return voidType; @@ -23505,7 +23525,7 @@ namespace ts { } /* falls through */ case SyntaxKind.NewExpression: - return checkCallExpression(node); + return checkCallExpression(node, checkMode); case SyntaxKind.TaggedTemplateExpression: return checkTaggedTemplateExpression(node); case SyntaxKind.ParenthesizedExpression: From 304e25cf69a9570234d8c2ad83c1a1f55b086635 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 2 Mar 2019 11:59:33 -0800 Subject: [PATCH 05/19] Add tests --- .../compiler/genericFunctionInference1.ts | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 tests/cases/compiler/genericFunctionInference1.ts diff --git a/tests/cases/compiler/genericFunctionInference1.ts b/tests/cases/compiler/genericFunctionInference1.ts new file mode 100644 index 0000000000000..c5416f32bda26 --- /dev/null +++ b/tests/cases/compiler/genericFunctionInference1.ts @@ -0,0 +1,82 @@ +// @strict: true +// @target: es2015 + +declare function pipe(ab: (...args: A) => B): (...args: A) => B; +declare function pipe(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; +declare function pipe(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; + +declare function list(a: T): T[]; +declare function box(x: V): { value: V }; + +const f00 = pipe(list); +const f01 = pipe(list, box); +const f02 = pipe(x => list(x), box); +const f03 = pipe(list, x => box(x)); +const f04 = pipe(x => list(x), x => box(x)) +const f05 = pipe(list, pipe(box)); +const f06 = pipe(x => list(x), pipe(box)); +const f07 = pipe(x => list(x), pipe(x => box(x))); + +const f10: (x: T) => T[] = pipe(list); +const f11: (x: T) => { value: T[] } = pipe(list, box); +const f12: (x: T) => { value: T[] } = pipe(x => list(x), box); +const f13: (x: T) => { value: T[] } = pipe(list, x => box(x)); +const f14: (x: T) => { value: T[] } = pipe(x => list(x), x => box(x)) +const f15: (x: T) => { value: T[] } = pipe(list, pipe(box)); +const f16: (x: T) => { value: T[] } = pipe(x => list(x), pipe(box)); +const f17: (x: T) => { value: T[] } = pipe(x => list(x), pipe(x => box(x))); + +// #29904.2 + +const fn20 = pipe((_a?: {}) => 1); + +// #29904.3 + +type Fn = (n: number) => number; +const fn30: Fn = pipe( + x => x + 1, + x => x * 2, +); + +const promise = Promise.resolve(1); +promise.then( + pipe( + x => x + 1, + x => x * 2, + ), +); + +// #29904.4 + +declare const getString: () => string; +declare const orUndefined: (name: string) => string | undefined; +declare const identity: (value: T) => T; + +const fn40 = pipe( + getString, + string => orUndefined(string), + identity, +); + +// #29904.6 + +declare const getArray: () => string[]; +declare const first: (ts: T[]) => T; + +const fn60 = pipe( + getArray, + x => x, + first, +); + +const fn61 = pipe( + getArray, + identity, + first, +); + +const fn62 = pipe( + getArray, + x => x, + x => first(x), +); From e7881a412ed1ff64f18ecd34486e253e91bece11 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 2 Mar 2019 11:59:41 -0800 Subject: [PATCH 06/19] Accept new baselines --- .../reference/genericFunctionInference1.js | 109 +++++ .../genericFunctionInference1.symbols | 381 +++++++++++++++++ .../reference/genericFunctionInference1.types | 397 ++++++++++++++++++ 3 files changed, 887 insertions(+) create mode 100644 tests/baselines/reference/genericFunctionInference1.js create mode 100644 tests/baselines/reference/genericFunctionInference1.symbols create mode 100644 tests/baselines/reference/genericFunctionInference1.types diff --git a/tests/baselines/reference/genericFunctionInference1.js b/tests/baselines/reference/genericFunctionInference1.js new file mode 100644 index 0000000000000..872656ba9c5c9 --- /dev/null +++ b/tests/baselines/reference/genericFunctionInference1.js @@ -0,0 +1,109 @@ +//// [genericFunctionInference1.ts] +declare function pipe(ab: (...args: A) => B): (...args: A) => B; +declare function pipe(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; +declare function pipe(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; + +declare function list(a: T): T[]; +declare function box(x: V): { value: V }; + +const f00 = pipe(list); +const f01 = pipe(list, box); +const f02 = pipe(x => list(x), box); +const f03 = pipe(list, x => box(x)); +const f04 = pipe(x => list(x), x => box(x)) +const f05 = pipe(list, pipe(box)); +const f06 = pipe(x => list(x), pipe(box)); +const f07 = pipe(x => list(x), pipe(x => box(x))); + +const f10: (x: T) => T[] = pipe(list); +const f11: (x: T) => { value: T[] } = pipe(list, box); +const f12: (x: T) => { value: T[] } = pipe(x => list(x), box); +const f13: (x: T) => { value: T[] } = pipe(list, x => box(x)); +const f14: (x: T) => { value: T[] } = pipe(x => list(x), x => box(x)) +const f15: (x: T) => { value: T[] } = pipe(list, pipe(box)); +const f16: (x: T) => { value: T[] } = pipe(x => list(x), pipe(box)); +const f17: (x: T) => { value: T[] } = pipe(x => list(x), pipe(x => box(x))); + +// #29904.2 + +const fn20 = pipe((_a?: {}) => 1); + +// #29904.3 + +type Fn = (n: number) => number; +const fn30: Fn = pipe( + x => x + 1, + x => x * 2, +); + +const promise = Promise.resolve(1); +promise.then( + pipe( + x => x + 1, + x => x * 2, + ), +); + +// #29904.4 + +declare const getString: () => string; +declare const orUndefined: (name: string) => string | undefined; +declare const identity: (value: T) => T; + +const fn40 = pipe( + getString, + string => orUndefined(string), + identity, +); + +// #29904.6 + +declare const getArray: () => string[]; +declare const first: (ts: T[]) => T; + +const fn60 = pipe( + getArray, + x => x, + first, +); + +const fn61 = pipe( + getArray, + identity, + first, +); + +const fn62 = pipe( + getArray, + x => x, + x => first(x), +); + + +//// [genericFunctionInference1.js] +"use strict"; +const f00 = pipe(list); +const f01 = pipe(list, box); +const f02 = pipe(x => list(x), box); +const f03 = pipe(list, x => box(x)); +const f04 = pipe(x => list(x), x => box(x)); +const f05 = pipe(list, pipe(box)); +const f06 = pipe(x => list(x), pipe(box)); +const f07 = pipe(x => list(x), pipe(x => box(x))); +const f10 = pipe(list); +const f11 = pipe(list, box); +const f12 = pipe(x => list(x), box); +const f13 = pipe(list, x => box(x)); +const f14 = pipe(x => list(x), x => box(x)); +const f15 = pipe(list, pipe(box)); +const f16 = pipe(x => list(x), pipe(box)); +const f17 = pipe(x => list(x), pipe(x => box(x))); +// #29904.2 +const fn20 = pipe((_a) => 1); +const fn30 = pipe(x => x + 1, x => x * 2); +const promise = Promise.resolve(1); +promise.then(pipe(x => x + 1, x => x * 2)); +const fn40 = pipe(getString, string => orUndefined(string), identity); +const fn60 = pipe(getArray, x => x, first); +const fn61 = pipe(getArray, identity, first); +const fn62 = pipe(getArray, x => x, x => first(x)); diff --git a/tests/baselines/reference/genericFunctionInference1.symbols b/tests/baselines/reference/genericFunctionInference1.symbols new file mode 100644 index 0000000000000..d49a20cec9c8e --- /dev/null +++ b/tests/baselines/reference/genericFunctionInference1.symbols @@ -0,0 +1,381 @@ +=== tests/cases/compiler/genericFunctionInference1.ts === +declare function pipe(ab: (...args: A) => B): (...args: A) => B; +>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) +>A : Symbol(A, Decl(genericFunctionInference1.ts, 0, 22)) +>B : Symbol(B, Decl(genericFunctionInference1.ts, 0, 38)) +>ab : Symbol(ab, Decl(genericFunctionInference1.ts, 0, 42)) +>args : Symbol(args, Decl(genericFunctionInference1.ts, 0, 47)) +>A : Symbol(A, Decl(genericFunctionInference1.ts, 0, 22)) +>B : Symbol(B, Decl(genericFunctionInference1.ts, 0, 38)) +>args : Symbol(args, Decl(genericFunctionInference1.ts, 0, 67)) +>A : Symbol(A, Decl(genericFunctionInference1.ts, 0, 22)) +>B : Symbol(B, Decl(genericFunctionInference1.ts, 0, 38)) + +declare function pipe(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; +>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) +>A : Symbol(A, Decl(genericFunctionInference1.ts, 1, 22)) +>B : Symbol(B, Decl(genericFunctionInference1.ts, 1, 38)) +>C : Symbol(C, Decl(genericFunctionInference1.ts, 1, 41)) +>ab : Symbol(ab, Decl(genericFunctionInference1.ts, 1, 45)) +>args : Symbol(args, Decl(genericFunctionInference1.ts, 1, 50)) +>A : Symbol(A, Decl(genericFunctionInference1.ts, 1, 22)) +>B : Symbol(B, Decl(genericFunctionInference1.ts, 1, 38)) +>bc : Symbol(bc, Decl(genericFunctionInference1.ts, 1, 67)) +>b : Symbol(b, Decl(genericFunctionInference1.ts, 1, 73)) +>B : Symbol(B, Decl(genericFunctionInference1.ts, 1, 38)) +>C : Symbol(C, Decl(genericFunctionInference1.ts, 1, 41)) +>args : Symbol(args, Decl(genericFunctionInference1.ts, 1, 87)) +>A : Symbol(A, Decl(genericFunctionInference1.ts, 1, 22)) +>C : Symbol(C, Decl(genericFunctionInference1.ts, 1, 41)) + +declare function pipe(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; +>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) +>A : Symbol(A, Decl(genericFunctionInference1.ts, 2, 22)) +>B : Symbol(B, Decl(genericFunctionInference1.ts, 2, 38)) +>C : Symbol(C, Decl(genericFunctionInference1.ts, 2, 41)) +>D : Symbol(D, Decl(genericFunctionInference1.ts, 2, 44)) +>ab : Symbol(ab, Decl(genericFunctionInference1.ts, 2, 48)) +>args : Symbol(args, Decl(genericFunctionInference1.ts, 2, 53)) +>A : Symbol(A, Decl(genericFunctionInference1.ts, 2, 22)) +>B : Symbol(B, Decl(genericFunctionInference1.ts, 2, 38)) +>bc : Symbol(bc, Decl(genericFunctionInference1.ts, 2, 70)) +>b : Symbol(b, Decl(genericFunctionInference1.ts, 2, 76)) +>B : Symbol(B, Decl(genericFunctionInference1.ts, 2, 38)) +>C : Symbol(C, Decl(genericFunctionInference1.ts, 2, 41)) +>cd : Symbol(cd, Decl(genericFunctionInference1.ts, 2, 87)) +>c : Symbol(c, Decl(genericFunctionInference1.ts, 2, 93)) +>C : Symbol(C, Decl(genericFunctionInference1.ts, 2, 41)) +>D : Symbol(D, Decl(genericFunctionInference1.ts, 2, 44)) +>args : Symbol(args, Decl(genericFunctionInference1.ts, 2, 107)) +>A : Symbol(A, Decl(genericFunctionInference1.ts, 2, 22)) +>D : Symbol(D, Decl(genericFunctionInference1.ts, 2, 44)) + +declare function list(a: T): T[]; +>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 4, 22)) +>a : Symbol(a, Decl(genericFunctionInference1.ts, 4, 25)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 4, 22)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 4, 22)) + +declare function box(x: V): { value: V }; +>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) +>V : Symbol(V, Decl(genericFunctionInference1.ts, 5, 21)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 5, 24)) +>V : Symbol(V, Decl(genericFunctionInference1.ts, 5, 21)) +>value : Symbol(value, Decl(genericFunctionInference1.ts, 5, 32)) +>V : Symbol(V, Decl(genericFunctionInference1.ts, 5, 21)) + +const f00 = pipe(list); +>f00 : Symbol(f00, Decl(genericFunctionInference1.ts, 7, 5)) +>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) +>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) + +const f01 = pipe(list, box); +>f01 : Symbol(f01, Decl(genericFunctionInference1.ts, 8, 5)) +>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) +>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) +>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) + +const f02 = pipe(x => list(x), box); +>f02 : Symbol(f02, Decl(genericFunctionInference1.ts, 9, 5)) +>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 9, 17)) +>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 9, 17)) +>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) + +const f03 = pipe(list, x => box(x)); +>f03 : Symbol(f03, Decl(genericFunctionInference1.ts, 10, 5)) +>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) +>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 10, 22)) +>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 10, 22)) + +const f04 = pipe(x => list(x), x => box(x)) +>f04 : Symbol(f04, Decl(genericFunctionInference1.ts, 11, 5)) +>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 11, 17)) +>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 11, 17)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 11, 30)) +>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 11, 30)) + +const f05 = pipe(list, pipe(box)); +>f05 : Symbol(f05, Decl(genericFunctionInference1.ts, 12, 5)) +>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) +>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) +>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) +>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) + +const f06 = pipe(x => list(x), pipe(box)); +>f06 : Symbol(f06, Decl(genericFunctionInference1.ts, 13, 5)) +>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 13, 17)) +>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 13, 17)) +>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) +>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) + +const f07 = pipe(x => list(x), pipe(x => box(x))); +>f07 : Symbol(f07, Decl(genericFunctionInference1.ts, 14, 5)) +>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 14, 17)) +>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 14, 17)) +>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 14, 36)) +>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 14, 36)) + +const f10: (x: T) => T[] = pipe(list); +>f10 : Symbol(f10, Decl(genericFunctionInference1.ts, 16, 5)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 16, 12)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 16, 15)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 16, 12)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 16, 12)) +>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) +>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) + +const f11: (x: T) => { value: T[] } = pipe(list, box); +>f11 : Symbol(f11, Decl(genericFunctionInference1.ts, 17, 5)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 17, 12)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 17, 15)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 17, 12)) +>value : Symbol(value, Decl(genericFunctionInference1.ts, 17, 25)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 17, 12)) +>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) +>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) +>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) + +const f12: (x: T) => { value: T[] } = pipe(x => list(x), box); +>f12 : Symbol(f12, Decl(genericFunctionInference1.ts, 18, 5)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 18, 12)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 18, 15)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 18, 12)) +>value : Symbol(value, Decl(genericFunctionInference1.ts, 18, 25)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 18, 12)) +>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 18, 46)) +>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 18, 46)) +>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) + +const f13: (x: T) => { value: T[] } = pipe(list, x => box(x)); +>f13 : Symbol(f13, Decl(genericFunctionInference1.ts, 19, 5)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 19, 12)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 19, 15)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 19, 12)) +>value : Symbol(value, Decl(genericFunctionInference1.ts, 19, 25)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 19, 12)) +>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) +>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 19, 51)) +>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 19, 51)) + +const f14: (x: T) => { value: T[] } = pipe(x => list(x), x => box(x)) +>f14 : Symbol(f14, Decl(genericFunctionInference1.ts, 20, 5)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 20, 12)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 20, 15)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 20, 12)) +>value : Symbol(value, Decl(genericFunctionInference1.ts, 20, 25)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 20, 12)) +>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 20, 46)) +>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 20, 46)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 20, 59)) +>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 20, 59)) + +const f15: (x: T) => { value: T[] } = pipe(list, pipe(box)); +>f15 : Symbol(f15, Decl(genericFunctionInference1.ts, 21, 5)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 21, 12)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 21, 15)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 21, 12)) +>value : Symbol(value, Decl(genericFunctionInference1.ts, 21, 25)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 21, 12)) +>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) +>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) +>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) +>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) + +const f16: (x: T) => { value: T[] } = pipe(x => list(x), pipe(box)); +>f16 : Symbol(f16, Decl(genericFunctionInference1.ts, 22, 5)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 22, 12)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 22, 15)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 22, 12)) +>value : Symbol(value, Decl(genericFunctionInference1.ts, 22, 25)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 22, 12)) +>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 22, 46)) +>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 22, 46)) +>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) +>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) + +const f17: (x: T) => { value: T[] } = pipe(x => list(x), pipe(x => box(x))); +>f17 : Symbol(f17, Decl(genericFunctionInference1.ts, 23, 5)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 23, 12)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 23, 15)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 23, 12)) +>value : Symbol(value, Decl(genericFunctionInference1.ts, 23, 25)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 23, 12)) +>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 23, 46)) +>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 23, 46)) +>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 23, 65)) +>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 23, 65)) + +// #29904.2 + +const fn20 = pipe((_a?: {}) => 1); +>fn20 : Symbol(fn20, Decl(genericFunctionInference1.ts, 27, 5)) +>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) +>_a : Symbol(_a, Decl(genericFunctionInference1.ts, 27, 19)) + +// #29904.3 + +type Fn = (n: number) => number; +>Fn : Symbol(Fn, Decl(genericFunctionInference1.ts, 27, 34)) +>n : Symbol(n, Decl(genericFunctionInference1.ts, 31, 11)) + +const fn30: Fn = pipe( +>fn30 : Symbol(fn30, Decl(genericFunctionInference1.ts, 32, 5)) +>Fn : Symbol(Fn, Decl(genericFunctionInference1.ts, 27, 34)) +>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) + + x => x + 1, +>x : Symbol(x, Decl(genericFunctionInference1.ts, 32, 22)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 32, 22)) + + x => x * 2, +>x : Symbol(x, Decl(genericFunctionInference1.ts, 33, 15)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 33, 15)) + +); + +const promise = Promise.resolve(1); +>promise : Symbol(promise, Decl(genericFunctionInference1.ts, 37, 5)) +>Promise.resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) + +promise.then( +>promise.then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) +>promise : Symbol(promise, Decl(genericFunctionInference1.ts, 37, 5)) +>then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) + + pipe( +>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) + + x => x + 1, +>x : Symbol(x, Decl(genericFunctionInference1.ts, 39, 9)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 39, 9)) + + x => x * 2, +>x : Symbol(x, Decl(genericFunctionInference1.ts, 40, 19)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 40, 19)) + + ), +); + +// #29904.4 + +declare const getString: () => string; +>getString : Symbol(getString, Decl(genericFunctionInference1.ts, 47, 13)) + +declare const orUndefined: (name: string) => string | undefined; +>orUndefined : Symbol(orUndefined, Decl(genericFunctionInference1.ts, 48, 13)) +>name : Symbol(name, Decl(genericFunctionInference1.ts, 48, 28)) + +declare const identity: (value: T) => T; +>identity : Symbol(identity, Decl(genericFunctionInference1.ts, 49, 13)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 49, 25)) +>value : Symbol(value, Decl(genericFunctionInference1.ts, 49, 28)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 49, 25)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 49, 25)) + +const fn40 = pipe( +>fn40 : Symbol(fn40, Decl(genericFunctionInference1.ts, 51, 5)) +>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) + + getString, +>getString : Symbol(getString, Decl(genericFunctionInference1.ts, 47, 13)) + + string => orUndefined(string), +>string : Symbol(string, Decl(genericFunctionInference1.ts, 52, 14)) +>orUndefined : Symbol(orUndefined, Decl(genericFunctionInference1.ts, 48, 13)) +>string : Symbol(string, Decl(genericFunctionInference1.ts, 52, 14)) + + identity, +>identity : Symbol(identity, Decl(genericFunctionInference1.ts, 49, 13)) + +); + +// #29904.6 + +declare const getArray: () => string[]; +>getArray : Symbol(getArray, Decl(genericFunctionInference1.ts, 59, 13)) + +declare const first: (ts: T[]) => T; +>first : Symbol(first, Decl(genericFunctionInference1.ts, 60, 13)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 60, 22)) +>ts : Symbol(ts, Decl(genericFunctionInference1.ts, 60, 25)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 60, 22)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 60, 22)) + +const fn60 = pipe( +>fn60 : Symbol(fn60, Decl(genericFunctionInference1.ts, 62, 5)) +>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) + + getArray, +>getArray : Symbol(getArray, Decl(genericFunctionInference1.ts, 59, 13)) + + x => x, +>x : Symbol(x, Decl(genericFunctionInference1.ts, 63, 13)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 63, 13)) + + first, +>first : Symbol(first, Decl(genericFunctionInference1.ts, 60, 13)) + +); + +const fn61 = pipe( +>fn61 : Symbol(fn61, Decl(genericFunctionInference1.ts, 68, 5)) +>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) + + getArray, +>getArray : Symbol(getArray, Decl(genericFunctionInference1.ts, 59, 13)) + + identity, +>identity : Symbol(identity, Decl(genericFunctionInference1.ts, 49, 13)) + + first, +>first : Symbol(first, Decl(genericFunctionInference1.ts, 60, 13)) + +); + +const fn62 = pipe( +>fn62 : Symbol(fn62, Decl(genericFunctionInference1.ts, 74, 5)) +>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) + + getArray, +>getArray : Symbol(getArray, Decl(genericFunctionInference1.ts, 59, 13)) + + x => x, +>x : Symbol(x, Decl(genericFunctionInference1.ts, 75, 13)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 75, 13)) + + x => first(x), +>x : Symbol(x, Decl(genericFunctionInference1.ts, 76, 11)) +>first : Symbol(first, Decl(genericFunctionInference1.ts, 60, 13)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 76, 11)) + +); + diff --git a/tests/baselines/reference/genericFunctionInference1.types b/tests/baselines/reference/genericFunctionInference1.types new file mode 100644 index 0000000000000..037e4a4971862 --- /dev/null +++ b/tests/baselines/reference/genericFunctionInference1.types @@ -0,0 +1,397 @@ +=== tests/cases/compiler/genericFunctionInference1.ts === +declare function pipe(ab: (...args: A) => B): (...args: A) => B; +>pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } +>ab : (...args: A) => B +>args : A +>args : A + +declare function pipe(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; +>pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } +>ab : (...args: A) => B +>args : A +>bc : (b: B) => C +>b : B +>args : A + +declare function pipe(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; +>pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } +>ab : (...args: A) => B +>args : A +>bc : (b: B) => C +>b : B +>cd : (c: C) => D +>c : C +>args : A + +declare function list(a: T): T[]; +>list : (a: T) => T[] +>a : T + +declare function box(x: V): { value: V }; +>box : (x: V) => { value: V; } +>x : V +>value : V + +const f00 = pipe(list); +>f00 : (a: any) => any[] +>pipe(list) : (a: any) => any[] +>pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } +>list : (a: T) => T[] + +const f01 = pipe(list, box); +>f01 : (a: any) => { value: any[]; } +>pipe(list, box) : (a: any) => { value: any[]; } +>pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } +>list : (a: T) => T[] +>box : (x: V) => { value: V; } + +const f02 = pipe(x => list(x), box); +>f02 : (x: any) => { value: any[]; } +>pipe(x => list(x), box) : (x: any) => { value: any[]; } +>pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } +>x => list(x) : (x: any) => any[] +>x : any +>list(x) : any[] +>list : (a: T) => T[] +>x : any +>box : (x: V) => { value: V; } + +const f03 = pipe(list, x => box(x)); +>f03 : (a: any) => { value: any[]; } +>pipe(list, x => box(x)) : (a: any) => { value: any[]; } +>pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } +>list : (a: T) => T[] +>x => box(x) : (x: any[]) => { value: any[]; } +>x : any[] +>box(x) : { value: any[]; } +>box : (x: V) => { value: V; } +>x : any[] + +const f04 = pipe(x => list(x), x => box(x)) +>f04 : (x: any) => { value: any[]; } +>pipe(x => list(x), x => box(x)) : (x: any) => { value: any[]; } +>pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } +>x => list(x) : (x: any) => any[] +>x : any +>list(x) : any[] +>list : (a: T) => T[] +>x : any +>x => box(x) : (x: any[]) => { value: any[]; } +>x : any[] +>box(x) : { value: any[]; } +>box : (x: V) => { value: V; } +>x : any[] + +const f05 = pipe(list, pipe(box)); +>f05 : (a: any) => { value: any[]; } +>pipe(list, pipe(box)) : (a: any) => { value: any[]; } +>pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } +>list : (a: T) => T[] +>pipe(box) : (x: any[]) => { value: any[]; } +>pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } +>box : (x: V) => { value: V; } + +const f06 = pipe(x => list(x), pipe(box)); +>f06 : (x: any) => { value: any[]; } +>pipe(x => list(x), pipe(box)) : (x: any) => { value: any[]; } +>pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } +>x => list(x) : (x: any) => any[] +>x : any +>list(x) : any[] +>list : (a: T) => T[] +>x : any +>pipe(box) : (x: any[]) => { value: any[]; } +>pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } +>box : (x: V) => { value: V; } + +const f07 = pipe(x => list(x), pipe(x => box(x))); +>f07 : (x: any) => { value: any[]; } +>pipe(x => list(x), pipe(x => box(x))) : (x: any) => { value: any[]; } +>pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } +>x => list(x) : (x: any) => any[] +>x : any +>list(x) : any[] +>list : (a: T) => T[] +>x : any +>pipe(x => box(x)) : (x: any[]) => { value: any[]; } +>pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } +>x => box(x) : (x: any[]) => { value: any[]; } +>x : any[] +>box(x) : { value: any[]; } +>box : (x: V) => { value: V; } +>x : any[] + +const f10: (x: T) => T[] = pipe(list); +>f10 : (x: T) => T[] +>x : T +>pipe(list) : (a: T) => T[] +>pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } +>list : (a: T) => T[] + +const f11: (x: T) => { value: T[] } = pipe(list, box); +>f11 : (x: T) => { value: T[]; } +>x : T +>value : T[] +>pipe(list, box) : (a: T) => { value: T[]; } +>pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } +>list : (a: T) => T[] +>box : (x: V) => { value: V; } + +const f12: (x: T) => { value: T[] } = pipe(x => list(x), box); +>f12 : (x: T) => { value: T[]; } +>x : T +>value : T[] +>pipe(x => list(x), box) : (x: T) => { value: T[]; } +>pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } +>x => list(x) : (x: T) => T[] +>x : T +>list(x) : T[] +>list : (a: T) => T[] +>x : T +>box : (x: V) => { value: V; } + +const f13: (x: T) => { value: T[] } = pipe(list, x => box(x)); +>f13 : (x: T) => { value: T[]; } +>x : T +>value : T[] +>pipe(list, x => box(x)) : (a: T) => { value: T[]; } +>pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } +>list : (a: T) => T[] +>x => box(x) : (x: T[]) => { value: T[]; } +>x : T[] +>box(x) : { value: T[]; } +>box : (x: V) => { value: V; } +>x : T[] + +const f14: (x: T) => { value: T[] } = pipe(x => list(x), x => box(x)) +>f14 : (x: T) => { value: T[]; } +>x : T +>value : T[] +>pipe(x => list(x), x => box(x)) : (x: T) => { value: T[]; } +>pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } +>x => list(x) : (x: T) => T[] +>x : T +>list(x) : T[] +>list : (a: T) => T[] +>x : T +>x => box(x) : (x: T[]) => { value: T[]; } +>x : T[] +>box(x) : { value: T[]; } +>box : (x: V) => { value: V; } +>x : T[] + +const f15: (x: T) => { value: T[] } = pipe(list, pipe(box)); +>f15 : (x: T) => { value: T[]; } +>x : T +>value : T[] +>pipe(list, pipe(box)) : (a: T) => { value: T[]; } +>pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } +>list : (a: T) => T[] +>pipe(box) : (x: T[]) => { value: T[]; } +>pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } +>box : (x: V) => { value: V; } + +const f16: (x: T) => { value: T[] } = pipe(x => list(x), pipe(box)); +>f16 : (x: T) => { value: T[]; } +>x : T +>value : T[] +>pipe(x => list(x), pipe(box)) : (x: T) => { value: T[]; } +>pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } +>x => list(x) : (x: T) => T[] +>x : T +>list(x) : T[] +>list : (a: T) => T[] +>x : T +>pipe(box) : (x: T[]) => { value: T[]; } +>pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } +>box : (x: V) => { value: V; } + +const f17: (x: T) => { value: T[] } = pipe(x => list(x), pipe(x => box(x))); +>f17 : (x: T) => { value: T[]; } +>x : T +>value : T[] +>pipe(x => list(x), pipe(x => box(x))) : (x: T) => { value: T[]; } +>pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } +>x => list(x) : (x: T) => T[] +>x : T +>list(x) : T[] +>list : (a: T) => T[] +>x : T +>pipe(x => box(x)) : (x: T[]) => { value: T[]; } +>pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } +>x => box(x) : (x: T[]) => { value: T[]; } +>x : T[] +>box(x) : { value: T[]; } +>box : (x: V) => { value: V; } +>x : T[] + +// #29904.2 + +const fn20 = pipe((_a?: {}) => 1); +>fn20 : (_a?: {} | undefined) => number +>pipe((_a?: {}) => 1) : (_a?: {} | undefined) => number +>pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } +>(_a?: {}) => 1 : (_a?: {} | undefined) => number +>_a : {} | undefined +>1 : 1 + +// #29904.3 + +type Fn = (n: number) => number; +>Fn : Fn +>n : number + +const fn30: Fn = pipe( +>fn30 : Fn +>pipe( x => x + 1, x => x * 2,) : (x: number) => number +>pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } + + x => x + 1, +>x => x + 1 : (x: number) => number +>x : number +>x + 1 : number +>x : number +>1 : 1 + + x => x * 2, +>x => x * 2 : (x: number) => number +>x : number +>x * 2 : number +>x : number +>2 : 2 + +); + +const promise = Promise.resolve(1); +>promise : Promise +>Promise.resolve(1) : Promise +>Promise.resolve : { (value: T | PromiseLike): Promise; (): Promise; } +>Promise : PromiseConstructor +>resolve : { (value: T | PromiseLike): Promise; (): Promise; } +>1 : 1 + +promise.then( +>promise.then( pipe( x => x + 1, x => x * 2, ),) : Promise +>promise.then : (onfulfilled?: ((value: number) => TResult1 | PromiseLike) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike) | null | undefined) => Promise +>promise : Promise +>then : (onfulfilled?: ((value: number) => TResult1 | PromiseLike) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike) | null | undefined) => Promise + + pipe( +>pipe( x => x + 1, x => x * 2, ) : (x: number) => number +>pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } + + x => x + 1, +>x => x + 1 : (x: number) => number +>x : number +>x + 1 : number +>x : number +>1 : 1 + + x => x * 2, +>x => x * 2 : (x: number) => number +>x : number +>x * 2 : number +>x : number +>2 : 2 + + ), +); + +// #29904.4 + +declare const getString: () => string; +>getString : () => string + +declare const orUndefined: (name: string) => string | undefined; +>orUndefined : (name: string) => string | undefined +>name : string + +declare const identity: (value: T) => T; +>identity : (value: T) => T +>value : T + +const fn40 = pipe( +>fn40 : () => string | undefined +>pipe( getString, string => orUndefined(string), identity,) : () => string | undefined +>pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } + + getString, +>getString : () => string + + string => orUndefined(string), +>string => orUndefined(string) : (string: string) => string | undefined +>string : string +>orUndefined(string) : string | undefined +>orUndefined : (name: string) => string | undefined +>string : string + + identity, +>identity : (value: T) => T + +); + +// #29904.6 + +declare const getArray: () => string[]; +>getArray : () => string[] + +declare const first: (ts: T[]) => T; +>first : (ts: T[]) => T +>ts : T[] + +const fn60 = pipe( +>fn60 : () => string +>pipe( getArray, x => x, first,) : () => string +>pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } + + getArray, +>getArray : () => string[] + + x => x, +>x => x : (x: string[]) => string[] +>x : string[] +>x : string[] + + first, +>first : (ts: T[]) => T + +); + +const fn61 = pipe( +>fn61 : () => string +>pipe( getArray, identity, first,) : () => string +>pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } + + getArray, +>getArray : () => string[] + + identity, +>identity : (value: T) => T + + first, +>first : (ts: T[]) => T + +); + +const fn62 = pipe( +>fn62 : () => string +>pipe( getArray, x => x, x => first(x),) : () => string +>pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } + + getArray, +>getArray : () => string[] + + x => x, +>x => x : (x: string[]) => string[] +>x : string[] +>x : string[] + + x => first(x), +>x => first(x) : (x: string[]) => string +>x : string[] +>first(x) : string +>first : (ts: T[]) => T +>x : string[] + +); + From c344ef3123023d71812290e96109686a3addbdb0 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 3 Mar 2019 14:34:38 -0800 Subject: [PATCH 07/19] Infer higher order function types when possible --- src/compiler/checker.ts | 117 +++++++++++++++++++++++++++++++++++++--- src/compiler/types.ts | 1 + 2 files changed, 112 insertions(+), 6 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a8dccb072b1a5..c3375bb6536aa 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3983,7 +3983,7 @@ namespace ts { context.flags &= ~NodeBuilderFlags.WriteTypeParametersInQualifiedName; // Avoids potential infinite loop when building for a claimspace with a generic const shouldUseGeneratedName = context.flags & NodeBuilderFlags.GenerateNamesForShadowedTypeParams && - type.symbol.declarations[0] && + type.symbol.declarations && type.symbol.declarations[0] && isTypeParameterDeclaration(type.symbol.declarations[0]) && typeParameterShadowsNameInScope(type, context); const name = shouldUseGeneratedName @@ -8375,9 +8375,23 @@ namespace ts { return undefined; } - function getSignatureInstantiation(signature: Signature, typeArguments: Type[] | undefined, isJavascript: boolean): Signature { - return getSignatureInstantiationWithoutFillingInTypeArguments(signature, fillMissingTypeArguments(typeArguments, signature.typeParameters, getMinTypeArgumentCount(signature.typeParameters), isJavascript)); + function getSignatureInstantiation(signature: Signature, typeArguments: Type[] | undefined, isJavascript: boolean, inferredTypeParameters?: ReadonlyArray): Signature { + const instantiatedSignature = getSignatureInstantiationWithoutFillingInTypeArguments(signature, fillMissingTypeArguments(typeArguments, signature.typeParameters, getMinTypeArgumentCount(signature.typeParameters), isJavascript)); + if (inferredTypeParameters) { + const returnSignature = getSingleCallSignature(getReturnTypeOfSignature(instantiatedSignature)); + if (returnSignature) { + const newReturnSignature = cloneSignature(returnSignature); + newReturnSignature.typeParameters = inferredTypeParameters; + newReturnSignature.target = returnSignature.target; + newReturnSignature.mapper = returnSignature.mapper; + const newInstantiatedSignature = cloneSignature(instantiatedSignature); + newInstantiatedSignature.resolvedReturnType = getOrCreateTypeFromSignature(newReturnSignature); + return newInstantiatedSignature; + } + } + return instantiatedSignature; } + function getSignatureInstantiationWithoutFillingInTypeArguments(signature: Signature, typeArguments: ReadonlyArray | undefined): Signature { const instantiations = signature.instantiations || (signature.instantiations = createMap()); const id = getTypeListId(typeArguments); @@ -8391,6 +8405,7 @@ namespace ts { function createSignatureInstantiation(signature: Signature, typeArguments: ReadonlyArray | undefined): Signature { return instantiateSignature(signature, createSignatureTypeMapper(signature, typeArguments), /*eraseTypeParameters*/ true); } + function createSignatureTypeMapper(signature: Signature, typeArguments: ReadonlyArray | undefined): TypeMapper { return createTypeMapper(signature.typeParameters!, typeArguments); } @@ -20652,7 +20667,7 @@ namespace ts { inferenceContext = createInferenceContext(candidate.typeParameters, candidate, /*flags*/ isInJSFile(node) ? InferenceFlags.AnyDefault : InferenceFlags.None); typeArgumentTypes = inferTypeArguments(node, candidate, args, excludeArgument, inferenceContext); } - checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, isInJSFile(candidate.declaration)); + checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, isInJSFile(candidate.declaration), inferenceContext && inferenceContext.inferredTypeParameters); // If the original signature has a generic rest type, instantiation may produce a // signature with different arity and we need to perform another arity check. if (getNonArrayRestType(candidate) && !hasCorrectArity(node, args, checkCandidate, signatureHelpTrailingComma)) { @@ -20677,7 +20692,7 @@ namespace ts { excludeArgument = undefined; if (inferenceContext) { const typeArgumentTypes = inferTypeArguments(node, candidate, args, excludeArgument, inferenceContext); - checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, isInJSFile(candidate.declaration)); + checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, isInJSFile(candidate.declaration), inferenceContext && inferenceContext.inferredTypeParameters); // If the original signature has a generic rest type, instantiation may produce a // signature with different arity and we need to perform another arity check. if (getNonArrayRestType(candidate) && !hasCorrectArity(node, args, checkCandidate, signatureHelpTrailingComma)) { @@ -23378,7 +23393,35 @@ namespace ts { if (contextualType) { const contextualSignature = getSingleCallSignature(getNonNullableType(contextualType)); if (contextualSignature && !contextualSignature.typeParameters) { - return getOrCreateTypeFromSignature(instantiateSignatureInContextOf(signature, contextualSignature, getContextualMapper(node))); + const context = getContextualMapper(node); + // We have an expression that is an argument of a generic function for which we are performing + // type argument inference. The expression is of a function type with a single generic call + // signature and a contextual function type with a single non-generic call signature. Now check + // if the outer function returns a function type with a single non-generic call signature and + // if some of the outer function type parameters have no inferences so far. If so, we can + // potentially add inferred type parameters to the outer function return type. + const returnSignature = context.signature && getSingleCallSignature(getReturnTypeOfSignature(context.signature)); + if (returnSignature && !returnSignature.typeParameters && !every(context.inferences, hasInferenceCandidates)) { + // Instantiate the expression type with its own type parameters as type arguments. This + // ensures that the type parameters are not erased to type any during type inference such + // that they can be inferred as actual types. + const uniqueTypeParameters = getUniqueTypeParameters(context, signature.typeParameters); + const strippedType = getOrCreateTypeFromSignature(getSignatureInstantiationWithoutFillingInTypeArguments(signature, uniqueTypeParameters)); + // Infer from the stripped expression type to the contextual type starting with an empty + // set of inference candidates. + const inferences = map(context.typeParameters, createInferenceInfo); + inferTypes(inferences, strippedType, contextualType); + // If we produced some inference candidates and if the type parameters for which we produced + // candidates do not already have existing inferences, we adopt the new inference candidates and + // add the type parameters of the expression type to the set of inferred type parameters for + // the outer function return type. + if (some(inferences, hasInferenceCandidates) && !hasOverlappingInferences(context.inferences, inferences)) { + mergeInferences(context.inferences, inferences); + context.inferredTypeParameters = concatenate(context.inferredTypeParameters, uniqueTypeParameters); + return strippedType; + } + } + return getOrCreateTypeFromSignature(instantiateSignatureInContextOf(signature, contextualSignature, context)); } } } @@ -23386,6 +23429,68 @@ namespace ts { return type; } + function hasInferenceCandidates(info: InferenceInfo) { + return !!(info.candidates || info.contraCandidates); + } + + function hasOverlappingInferences(a: InferenceInfo[], b: InferenceInfo[]) { + for (let i = 0; i < a.length; i++) { + if (hasInferenceCandidates(a[i]) && hasInferenceCandidates(b[i])) { + return true; + } + } + return false; + } + + function mergeInferences(target: InferenceInfo[], source: InferenceInfo[]) { + for (let i = 0; i < target.length; i++) { + if (!hasInferenceCandidates(target[i]) && hasInferenceCandidates(source[i])) { + target[i] = source[i]; + } + } + } + + function getUniqueTypeParameters(context: InferenceContext, typeParameters: ReadonlyArray): ReadonlyArray { + let result: TypeParameter[] = []; + let oldTypeParameters: TypeParameter[] | undefined; + let newTypeParameters: TypeParameter[] | undefined; + for (const tp of typeParameters) { + const name = tp.symbol.escapedName; + if (hasInferredTypeParameterByName(context, name)) { + const symbol = createSymbol(SymbolFlags.TypeParameter, getUniqueInferredTypeParameterName(context, name)); + const newTypeParameter = createTypeParameter(symbol); + newTypeParameter.target = tp; + oldTypeParameters = append(oldTypeParameters, tp); + newTypeParameters = append(newTypeParameters, newTypeParameter); + result.push(newTypeParameter); + } + else { + result.push(tp); + } + } + if (newTypeParameters) { + const mapper = createTypeMapper(oldTypeParameters!, newTypeParameters); + for (const tp of newTypeParameters) { + tp.mapper = mapper; + } + } + return result; + } + + function hasInferredTypeParameterByName(context: InferenceContext, name: __String) { + return some(context.inferredTypeParameters, tp => tp.symbol.escapedName === name); + } + + function getUniqueInferredTypeParameterName(context: InferenceContext, baseName: __String) { + let index = 1; + while (true) { + const augmentedName = <__String>(baseName + index); + if (!hasInferredTypeParameterByName(context, augmentedName)) { + return augmentedName; + } + } + } + /** * Returns the type of an expression. Unlike checkExpression, this function is simply concerned * with computing the type and may not fully check all contained sub-expressions for errors. diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 42fd1126d4cba..5217dd66fb494 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -4391,6 +4391,7 @@ namespace ts { flags: InferenceFlags; // Inference flags compareTypes: TypeComparer; // Type comparer function returnMapper?: TypeMapper; // Type mapper for inferences from return types (if any) + inferredTypeParameters?: ReadonlyArray; } /* @internal */ From c58819e9c2248294da8cbdc76ce14ae8d0388536 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 3 Mar 2019 17:01:11 -0800 Subject: [PATCH 08/19] Accept new baselines --- .../contextualSignatureInstantiation1.types | 8 +++--- .../contextualSignatureInstantiation2.types | 4 +-- .../reference/genericFunctionInference1.types | 26 +++++++++---------- .../genericTypeParameterEquivalence2.types | 20 +++++++------- 4 files changed, 29 insertions(+), 29 deletions(-) diff --git a/tests/baselines/reference/contextualSignatureInstantiation1.types b/tests/baselines/reference/contextualSignatureInstantiation1.types index 82e0d7cb6fd67..9bb1ff030ca62 100644 --- a/tests/baselines/reference/contextualSignatureInstantiation1.types +++ b/tests/baselines/reference/contextualSignatureInstantiation1.types @@ -15,8 +15,8 @@ var e = (x: string, y?: K) => x.length; >length : number var r99 = map(e); // should be {}[] for S since a generic lambda is not inferentially typed ->r99 : (a: {}[]) => number[] ->map(e) : (a: {}[]) => number[] +>r99 : (a: string[]) => number[] +>map(e) : (a: string[]) => number[] >map : (f: (x: S) => T) => (a: S[]) => T[] >e : (x: string, y?: K) => number @@ -37,8 +37,8 @@ var e2 = (x: string, y?: K) => x.length; >length : number var r100 = map2(e2); // type arg inference should fail for S since a generic lambda is not inferentially typed. Falls back to { length: number } ->r100 : (a: { length: number; }[]) => number[] ->map2(e2) : (a: { length: number; }[]) => number[] +>r100 : (a: string[]) => number[] +>map2(e2) : (a: string[]) => number[] >map2 : (f: (x: S) => T) => (a: S[]) => T[] >e2 : (x: string, y?: K) => number diff --git a/tests/baselines/reference/contextualSignatureInstantiation2.types b/tests/baselines/reference/contextualSignatureInstantiation2.types index dbd526ab55648..44776b5c01e4d 100644 --- a/tests/baselines/reference/contextualSignatureInstantiation2.types +++ b/tests/baselines/reference/contextualSignatureInstantiation2.types @@ -31,8 +31,8 @@ var id: (x:T) => T; >x : T var r23 = dot(id)(id); ->r23 : (_: {}) => {} ->dot(id)(id) : (_: {}) => {} +>r23 : (_: T) => {} +>dot(id)(id) : (_: T) => {} >dot(id) : (g: (_: U) => {}) => (_: U) => {} >dot : (f: (_: T) => S) => (g: (_: U) => T) => (_: U) => S >id : (x: T) => T diff --git a/tests/baselines/reference/genericFunctionInference1.types b/tests/baselines/reference/genericFunctionInference1.types index 037e4a4971862..cf85c1b5afb6c 100644 --- a/tests/baselines/reference/genericFunctionInference1.types +++ b/tests/baselines/reference/genericFunctionInference1.types @@ -33,14 +33,14 @@ declare function box(x: V): { value: V }; >value : V const f00 = pipe(list); ->f00 : (a: any) => any[] ->pipe(list) : (a: any) => any[] +>f00 : (a: T) => T[] +>pipe(list) : (a: T) => T[] >pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } >list : (a: T) => T[] const f01 = pipe(list, box); ->f01 : (a: any) => { value: any[]; } ->pipe(list, box) : (a: any) => { value: any[]; } +>f01 : (a: T) => { value: T[]; } +>pipe(list, box) : (a: T) => { value: T[]; } >pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } >list : (a: T) => T[] >box : (x: V) => { value: V; } @@ -57,15 +57,15 @@ const f02 = pipe(x => list(x), box); >box : (x: V) => { value: V; } const f03 = pipe(list, x => box(x)); ->f03 : (a: any) => { value: any[]; } ->pipe(list, x => box(x)) : (a: any) => { value: any[]; } +>f03 : (a: T) => { value: T[]; } +>pipe(list, x => box(x)) : (a: T) => { value: T[]; } >pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } >list : (a: T) => T[] ->x => box(x) : (x: any[]) => { value: any[]; } ->x : any[] ->box(x) : { value: any[]; } +>x => box(x) : (x: T[]) => { value: T[]; } +>x : T[] +>box(x) : { value: T[]; } >box : (x: V) => { value: V; } ->x : any[] +>x : T[] const f04 = pipe(x => list(x), x => box(x)) >f04 : (x: any) => { value: any[]; } @@ -83,11 +83,11 @@ const f04 = pipe(x => list(x), x => box(x)) >x : any[] const f05 = pipe(list, pipe(box)); ->f05 : (a: any) => { value: any[]; } ->pipe(list, pipe(box)) : (a: any) => { value: any[]; } +>f05 : (a: T) => { value: T[]; } +>pipe(list, pipe(box)) : (a: T) => { value: T[]; } >pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } >list : (a: T) => T[] ->pipe(box) : (x: any[]) => { value: any[]; } +>pipe(box) : (x: T[]) => { value: T[]; } >pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } >box : (x: V) => { value: V; } diff --git a/tests/baselines/reference/genericTypeParameterEquivalence2.types b/tests/baselines/reference/genericTypeParameterEquivalence2.types index 1fafa5ad69d34..63b9bb774f5cc 100644 --- a/tests/baselines/reference/genericTypeParameterEquivalence2.types +++ b/tests/baselines/reference/genericTypeParameterEquivalence2.types @@ -129,8 +129,8 @@ function curry1(f: (a: A, b: B) => C): (ax: A) => (bx: B) => C { } var cfilter = curry1(filter); ->cfilter : (ax: {}) => (bx: {}) => {}[] ->curry1(filter) : (ax: {}) => (bx: {}) => {}[] +>cfilter : (ax: (a: A) => boolean) => (bx: A[]) => A[] +>curry1(filter) : (ax: (a: A) => boolean) => (bx: A[]) => A[] >curry1 : (f: (a: A, b: B) => C) => (ax: A) => (bx: B) => C >filter : (f: (a: A) => boolean, ar: A[]) => A[] @@ -149,11 +149,11 @@ function countWhere_1(pred: (a: A) => boolean): (a: A[]) => number { >a : A[] return compose(length2, cfilter(pred)); ->compose(length2, cfilter(pred)) : (a: {}) => number +>compose(length2, cfilter(pred)) : (a: A[]) => number >compose : (f: (b: B) => C, g: (a: A) => B) => (a: A) => C >length2 : (ar: A[]) => number ->cfilter(pred) : (bx: {}) => {}[] ->cfilter : (ax: {}) => (bx: {}) => {}[] +>cfilter(pred) : (bx: A[]) => A[] +>cfilter : (ax: (a: A) => boolean) => (bx: A[]) => A[] >pred : (a: A) => boolean } @@ -164,14 +164,14 @@ function countWhere_2(pred: (a: A) => boolean): (a: A[]) => number { >a : A[] var where = cfilter(pred); ->where : (bx: {}) => {}[] ->cfilter(pred) : (bx: {}) => {}[] ->cfilter : (ax: {}) => (bx: {}) => {}[] +>where : (bx: A[]) => A[] +>cfilter(pred) : (bx: A[]) => A[] +>cfilter : (ax: (a: A) => boolean) => (bx: A[]) => A[] >pred : (a: A) => boolean return compose(length2, where); ->compose(length2, where) : (a: {}) => number +>compose(length2, where) : (a: A[]) => number >compose : (f: (b: B) => C, g: (a: A) => B) => (a: A) => C >length2 : (ar: A[]) => number ->where : (bx: {}) => {}[] +>where : (bx: A[]) => A[] } From 919ade1dbd3f7e6acfc71b02defb622c0bcb8d43 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 4 Mar 2019 10:57:08 -0800 Subject: [PATCH 09/19] Improve scheme for creating unique type parameter names --- src/compiler/checker.ts | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index c3375bb6536aa..d97abd4a5d0b3 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -23456,8 +23456,9 @@ namespace ts { let newTypeParameters: TypeParameter[] | undefined; for (const tp of typeParameters) { const name = tp.symbol.escapedName; - if (hasInferredTypeParameterByName(context, name)) { - const symbol = createSymbol(SymbolFlags.TypeParameter, getUniqueInferredTypeParameterName(context, name)); + if (hasTypeParameterByName(context.inferredTypeParameters, name) || hasTypeParameterByName(result, name)) { + const newName = getUniqueTypeParameterName(concatenate(context.inferredTypeParameters, result), name); + const symbol = createSymbol(SymbolFlags.TypeParameter, newName); const newTypeParameter = createTypeParameter(symbol); newTypeParameter.target = tp; oldTypeParameters = append(oldTypeParameters, tp); @@ -23477,15 +23478,17 @@ namespace ts { return result; } - function hasInferredTypeParameterByName(context: InferenceContext, name: __String) { - return some(context.inferredTypeParameters, tp => tp.symbol.escapedName === name); + function hasTypeParameterByName(typeParameters: ReadonlyArray | undefined, name: __String) { + return some(typeParameters, tp => tp.symbol.escapedName === name); } - function getUniqueInferredTypeParameterName(context: InferenceContext, baseName: __String) { - let index = 1; - while (true) { - const augmentedName = <__String>(baseName + index); - if (!hasInferredTypeParameterByName(context, augmentedName)) { + function getUniqueTypeParameterName(typeParameters: ReadonlyArray, baseName: __String) { + let len = (baseName).length; + while (len > 1 && (baseName).charCodeAt(len - 1) >= CharacterCodes._0 && (baseName).charCodeAt(len - 1) <= CharacterCodes._9) len--; + const s = (baseName).slice(0, len); + for (let index = 1; true; index++) { + const augmentedName = <__String>(s + index); + if (!hasTypeParameterByName(typeParameters, augmentedName)) { return augmentedName; } } From 549c68451708a9c48b2127ba6bc6618354366fdd Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 4 Mar 2019 11:02:55 -0800 Subject: [PATCH 10/19] Minor fix --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d97abd4a5d0b3..9ca8b60d36a83 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -22104,7 +22104,7 @@ namespace ts { forEachReturnStatement(func.body, returnStatement => { const expr = returnStatement.expression; if (expr) { - let type = checkExpressionCached(expr, checkMode && checkMode && checkMode & ~CheckMode.SkipGenericFunctions); + let type = checkExpressionCached(expr, checkMode && checkMode & ~CheckMode.SkipGenericFunctions); if (functionFlags & FunctionFlags.Async) { // From within an async function you can return either a non-promise value or a promise. Any // Promise/A+ compatible implementation will always assimilate any foreign promise, so the From 22c934a065d56f0578a58b6258fcc8775ffd4cf0 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 4 Mar 2019 11:07:02 -0800 Subject: [PATCH 11/19] Add tests --- .../compiler/genericFunctionInference1.ts | 135 ++++++++++++++++-- 1 file changed, 120 insertions(+), 15 deletions(-) diff --git a/tests/cases/compiler/genericFunctionInference1.ts b/tests/cases/compiler/genericFunctionInference1.ts index c5416f32bda26..f2a71ca7f0275 100644 --- a/tests/cases/compiler/genericFunctionInference1.ts +++ b/tests/cases/compiler/genericFunctionInference1.ts @@ -7,24 +7,129 @@ declare function pipe(ab: (...args: A) => B, bc: (b: B declare function list(a: T): T[]; declare function box(x: V): { value: V }; +declare function foo(x: T): T; const f00 = pipe(list); const f01 = pipe(list, box); -const f02 = pipe(x => list(x), box); -const f03 = pipe(list, x => box(x)); -const f04 = pipe(x => list(x), x => box(x)) -const f05 = pipe(list, pipe(box)); -const f06 = pipe(x => list(x), pipe(box)); -const f07 = pipe(x => list(x), pipe(x => box(x))); - -const f10: (x: T) => T[] = pipe(list); -const f11: (x: T) => { value: T[] } = pipe(list, box); -const f12: (x: T) => { value: T[] } = pipe(x => list(x), box); -const f13: (x: T) => { value: T[] } = pipe(list, x => box(x)); -const f14: (x: T) => { value: T[] } = pipe(x => list(x), x => box(x)) -const f15: (x: T) => { value: T[] } = pipe(list, pipe(box)); -const f16: (x: T) => { value: T[] } = pipe(x => list(x), pipe(box)); -const f17: (x: T) => { value: T[] } = pipe(x => list(x), pipe(x => box(x))); +const f02 = pipe(box, list); +const f03 = pipe(x => list(x), box); +const f04 = pipe(list, x => box(x)); +const f05 = pipe(x => list(x), x => box(x)) +const f06 = pipe(list, pipe(box)); +const f07 = pipe(x => list(x), pipe(box)); +const f08 = pipe(x => list(x), pipe(x => box(x))); +const f09 = pipe(list, x => x.length); +const f10 = pipe(foo); +const f11 = pipe(foo, foo); + +const g00: (x: T) => T[] = pipe(list); +const g01: (x: T) => { value: T[] } = pipe(list, box); +const g02: (x: T) => { value: T }[] = pipe(box, list); +const g03: (x: T) => { value: T[] } = pipe(x => list(x), box); +const g04: (x: T) => { value: T[] } = pipe(list, x => box(x)); +const g05: (x: T) => { value: T[] } = pipe(x => list(x), x => box(x)) +const g06: (x: T) => { value: T[] } = pipe(list, pipe(box)); +const g07: (x: T) => { value: T[] } = pipe(x => list(x), pipe(box)); +const g08: (x: T) => { value: T[] } = pipe(x => list(x), pipe(x => box(x))); +const g09: (x: T) => number = pipe(list, x => x.length); +const g10: (x: T) => T = pipe(foo); +const g12: (x: T) => T = pipe(foo, foo); + +declare function pipe2(ab: (a: A) => B, cd: (c: C) => D): (a: [A, C]) => [B, D]; + +const f20 = pipe2(list, box); +const f21 = pipe2(box, list); +const f22 = pipe2(list, list); +const f23 = pipe2(box, box); +const f24 = pipe2(f20, f20); +const f25 = pipe2(foo, foo); +const f26 = pipe2(f25, f25); + +declare function pipe3(ab: (a: A) => B, ac: (a: A) => C): (a: A) => [B, C]; + +const f30 = pipe3(list, box); +const f31 = pipe3(box, list); +const f32 = pipe3(list, list); + +declare function pipe4(funcs: [(a: A) => B, (b: B) => C]): (a: A) => C; + +const f40 = pipe4([list, box]); +const f41 = pipe4([box, list]); + +declare function pipe5(f: (a: A) => B): { f: (a: A) => B }; + +const f50 = pipe5(list); // No higher order inference + +// #417 + +function mirror(f: (a: A) => B): (a: A) => B { return f; } +var identityM = mirror(identity); + +var x = 1; +var y = identity(x); +var z = identityM(x); + +// #3038 + +export function keyOf(value: { key: a; }): a { + return value.key; +} +export interface Data { + key: number; + value: Date; +} + +var data: Data[] = []; + +declare function toKeys(values: a[], toKey: (value: a) => string): string[]; + +toKeys(data, keyOf); // Error + +// #9366 + +function flip(f: (a: a, b: b) => c): (b: b, a: a) => c { + return (b: b, a: a) => f(a, b); +} +function zip(x: T, y: U): [T, U] { + return [x, y]; +} + +var expected: (y: U, x: T) => [T, U] = flip(zip); +var actual = flip(zip); + +// #9366 + +const map = (transform: (t: T) => U) => + (arr: T[]) => arr.map(transform) + +const identityStr = (t: string) => t; + +const arr: string[] = map(identityStr)(['a']); +const arr1: string[] = map(identity)(['a']); + +// #9949 + +function of2(one: a, two: b): [a, b] { + return [one, two]; +} + +const flipped = flip(of2); + +// #29904.1 + +type Component

= (props: P) => {}; + +declare const myHoc1:

(C: Component

) => Component

; +declare const myHoc2:

(C: Component

) => Component

; + +declare const MyComponent1: Component<{ foo: 1 }>; + +const enhance = pipe( + myHoc1, + myHoc2, +); + +const MyComponent2 = enhance(MyComponent1); // #29904.2 From 5fe8ebb502f90742a0c53b20d7bc38439ea59d70 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 4 Mar 2019 11:07:11 -0800 Subject: [PATCH 12/19] Accept new baselines --- .../genericFunctionInference1.errors.txt | 193 +++++ .../reference/genericFunctionInference1.js | 218 ++++- .../genericFunctionInference1.symbols | 759 ++++++++++++++---- .../reference/genericFunctionInference1.types | 460 ++++++++++- 4 files changed, 1427 insertions(+), 203 deletions(-) create mode 100644 tests/baselines/reference/genericFunctionInference1.errors.txt diff --git a/tests/baselines/reference/genericFunctionInference1.errors.txt b/tests/baselines/reference/genericFunctionInference1.errors.txt new file mode 100644 index 0000000000000..9b082d39ab2ba --- /dev/null +++ b/tests/baselines/reference/genericFunctionInference1.errors.txt @@ -0,0 +1,193 @@ +tests/cases/compiler/genericFunctionInference1.ts(83,14): error TS2345: Argument of type '(value: { key: a; }) => a' is not assignable to parameter of type '(value: Data) => string'. + Type 'number' is not assignable to type 'string'. + + +==== tests/cases/compiler/genericFunctionInference1.ts (1 errors) ==== + declare function pipe(ab: (...args: A) => B): (...args: A) => B; + declare function pipe(ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; + declare function pipe(ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; + + declare function list(a: T): T[]; + declare function box(x: V): { value: V }; + declare function foo(x: T): T; + + const f00 = pipe(list); + const f01 = pipe(list, box); + const f02 = pipe(box, list); + const f03 = pipe(x => list(x), box); + const f04 = pipe(list, x => box(x)); + const f05 = pipe(x => list(x), x => box(x)) + const f06 = pipe(list, pipe(box)); + const f07 = pipe(x => list(x), pipe(box)); + const f08 = pipe(x => list(x), pipe(x => box(x))); + const f09 = pipe(list, x => x.length); + const f10 = pipe(foo); + const f11 = pipe(foo, foo); + + const g00: (x: T) => T[] = pipe(list); + const g01: (x: T) => { value: T[] } = pipe(list, box); + const g02: (x: T) => { value: T }[] = pipe(box, list); + const g03: (x: T) => { value: T[] } = pipe(x => list(x), box); + const g04: (x: T) => { value: T[] } = pipe(list, x => box(x)); + const g05: (x: T) => { value: T[] } = pipe(x => list(x), x => box(x)) + const g06: (x: T) => { value: T[] } = pipe(list, pipe(box)); + const g07: (x: T) => { value: T[] } = pipe(x => list(x), pipe(box)); + const g08: (x: T) => { value: T[] } = pipe(x => list(x), pipe(x => box(x))); + const g09: (x: T) => number = pipe(list, x => x.length); + const g10: (x: T) => T = pipe(foo); + const g12: (x: T) => T = pipe(foo, foo); + + declare function pipe2(ab: (a: A) => B, cd: (c: C) => D): (a: [A, C]) => [B, D]; + + const f20 = pipe2(list, box); + const f21 = pipe2(box, list); + const f22 = pipe2(list, list); + const f23 = pipe2(box, box); + const f24 = pipe2(f20, f20); + const f25 = pipe2(foo, foo); + const f26 = pipe2(f25, f25); + + declare function pipe3(ab: (a: A) => B, ac: (a: A) => C): (a: A) => [B, C]; + + const f30 = pipe3(list, box); + const f31 = pipe3(box, list); + const f32 = pipe3(list, list); + + declare function pipe4(funcs: [(a: A) => B, (b: B) => C]): (a: A) => C; + + const f40 = pipe4([list, box]); + const f41 = pipe4([box, list]); + + declare function pipe5(f: (a: A) => B): { f: (a: A) => B }; + + const f50 = pipe5(list); // No higher order inference + + // #417 + + function mirror(f: (a: A) => B): (a: A) => B { return f; } + var identityM = mirror(identity); + + var x = 1; + var y = identity(x); + var z = identityM(x); + + // #3038 + + export function keyOf(value: { key: a; }): a { + return value.key; + } + export interface Data { + key: number; + value: Date; + } + + var data: Data[] = []; + + declare function toKeys(values: a[], toKey: (value: a) => string): string[]; + + toKeys(data, keyOf); // Error + ~~~~~ +!!! error TS2345: Argument of type '(value: { key: a; }) => a' is not assignable to parameter of type '(value: Data) => string'. +!!! error TS2345: Type 'number' is not assignable to type 'string'. + + // #9366 + + function flip(f: (a: a, b: b) => c): (b: b, a: a) => c { + return (b: b, a: a) => f(a, b); + } + function zip(x: T, y: U): [T, U] { + return [x, y]; + } + + var expected: (y: U, x: T) => [T, U] = flip(zip); + var actual = flip(zip); + + // #9366 + + const map = (transform: (t: T) => U) => + (arr: T[]) => arr.map(transform) + + const identityStr = (t: string) => t; + + const arr: string[] = map(identityStr)(['a']); + const arr1: string[] = map(identity)(['a']); + + // #9949 + + function of2(one: a, two: b): [a, b] { + return [one, two]; + } + + const flipped = flip(of2); + + // #29904.1 + + type Component

= (props: P) => {}; + + declare const myHoc1:

(C: Component

) => Component

; + declare const myHoc2:

(C: Component

) => Component

; + + declare const MyComponent1: Component<{ foo: 1 }>; + + const enhance = pipe( + myHoc1, + myHoc2, + ); + + const MyComponent2 = enhance(MyComponent1); + + // #29904.2 + + const fn20 = pipe((_a?: {}) => 1); + + // #29904.3 + + type Fn = (n: number) => number; + const fn30: Fn = pipe( + x => x + 1, + x => x * 2, + ); + + const promise = Promise.resolve(1); + promise.then( + pipe( + x => x + 1, + x => x * 2, + ), + ); + + // #29904.4 + + declare const getString: () => string; + declare const orUndefined: (name: string) => string | undefined; + declare const identity: (value: T) => T; + + const fn40 = pipe( + getString, + string => orUndefined(string), + identity, + ); + + // #29904.6 + + declare const getArray: () => string[]; + declare const first: (ts: T[]) => T; + + const fn60 = pipe( + getArray, + x => x, + first, + ); + + const fn61 = pipe( + getArray, + identity, + first, + ); + + const fn62 = pipe( + getArray, + x => x, + x => first(x), + ); + \ No newline at end of file diff --git a/tests/baselines/reference/genericFunctionInference1.js b/tests/baselines/reference/genericFunctionInference1.js index 872656ba9c5c9..4e89f9c0795e5 100644 --- a/tests/baselines/reference/genericFunctionInference1.js +++ b/tests/baselines/reference/genericFunctionInference1.js @@ -5,24 +5,129 @@ declare function pipe(ab: (...args: A) => B, bc: (b: B declare function list(a: T): T[]; declare function box(x: V): { value: V }; +declare function foo(x: T): T; const f00 = pipe(list); const f01 = pipe(list, box); -const f02 = pipe(x => list(x), box); -const f03 = pipe(list, x => box(x)); -const f04 = pipe(x => list(x), x => box(x)) -const f05 = pipe(list, pipe(box)); -const f06 = pipe(x => list(x), pipe(box)); -const f07 = pipe(x => list(x), pipe(x => box(x))); - -const f10: (x: T) => T[] = pipe(list); -const f11: (x: T) => { value: T[] } = pipe(list, box); -const f12: (x: T) => { value: T[] } = pipe(x => list(x), box); -const f13: (x: T) => { value: T[] } = pipe(list, x => box(x)); -const f14: (x: T) => { value: T[] } = pipe(x => list(x), x => box(x)) -const f15: (x: T) => { value: T[] } = pipe(list, pipe(box)); -const f16: (x: T) => { value: T[] } = pipe(x => list(x), pipe(box)); -const f17: (x: T) => { value: T[] } = pipe(x => list(x), pipe(x => box(x))); +const f02 = pipe(box, list); +const f03 = pipe(x => list(x), box); +const f04 = pipe(list, x => box(x)); +const f05 = pipe(x => list(x), x => box(x)) +const f06 = pipe(list, pipe(box)); +const f07 = pipe(x => list(x), pipe(box)); +const f08 = pipe(x => list(x), pipe(x => box(x))); +const f09 = pipe(list, x => x.length); +const f10 = pipe(foo); +const f11 = pipe(foo, foo); + +const g00: (x: T) => T[] = pipe(list); +const g01: (x: T) => { value: T[] } = pipe(list, box); +const g02: (x: T) => { value: T }[] = pipe(box, list); +const g03: (x: T) => { value: T[] } = pipe(x => list(x), box); +const g04: (x: T) => { value: T[] } = pipe(list, x => box(x)); +const g05: (x: T) => { value: T[] } = pipe(x => list(x), x => box(x)) +const g06: (x: T) => { value: T[] } = pipe(list, pipe(box)); +const g07: (x: T) => { value: T[] } = pipe(x => list(x), pipe(box)); +const g08: (x: T) => { value: T[] } = pipe(x => list(x), pipe(x => box(x))); +const g09: (x: T) => number = pipe(list, x => x.length); +const g10: (x: T) => T = pipe(foo); +const g12: (x: T) => T = pipe(foo, foo); + +declare function pipe2(ab: (a: A) => B, cd: (c: C) => D): (a: [A, C]) => [B, D]; + +const f20 = pipe2(list, box); +const f21 = pipe2(box, list); +const f22 = pipe2(list, list); +const f23 = pipe2(box, box); +const f24 = pipe2(f20, f20); +const f25 = pipe2(foo, foo); +const f26 = pipe2(f25, f25); + +declare function pipe3(ab: (a: A) => B, ac: (a: A) => C): (a: A) => [B, C]; + +const f30 = pipe3(list, box); +const f31 = pipe3(box, list); +const f32 = pipe3(list, list); + +declare function pipe4(funcs: [(a: A) => B, (b: B) => C]): (a: A) => C; + +const f40 = pipe4([list, box]); +const f41 = pipe4([box, list]); + +declare function pipe5(f: (a: A) => B): { f: (a: A) => B }; + +const f50 = pipe5(list); // No higher order inference + +// #417 + +function mirror(f: (a: A) => B): (a: A) => B { return f; } +var identityM = mirror(identity); + +var x = 1; +var y = identity(x); +var z = identityM(x); + +// #3038 + +export function keyOf(value: { key: a; }): a { + return value.key; +} +export interface Data { + key: number; + value: Date; +} + +var data: Data[] = []; + +declare function toKeys(values: a[], toKey: (value: a) => string): string[]; + +toKeys(data, keyOf); // Error + +// #9366 + +function flip(f: (a: a, b: b) => c): (b: b, a: a) => c { + return (b: b, a: a) => f(a, b); +} +function zip(x: T, y: U): [T, U] { + return [x, y]; +} + +var expected: (y: U, x: T) => [T, U] = flip(zip); +var actual = flip(zip); + +// #9366 + +const map = (transform: (t: T) => U) => + (arr: T[]) => arr.map(transform) + +const identityStr = (t: string) => t; + +const arr: string[] = map(identityStr)(['a']); +const arr1: string[] = map(identity)(['a']); + +// #9949 + +function of2(one: a, two: b): [a, b] { + return [one, two]; +} + +const flipped = flip(of2); + +// #29904.1 + +type Component

= (props: P) => {}; + +declare const myHoc1:

(C: Component

) => Component

; +declare const myHoc2:

(C: Component

) => Component

; + +declare const MyComponent1: Component<{ foo: 1 }>; + +const enhance = pipe( + myHoc1, + myHoc2, +); + +const MyComponent2 = enhance(MyComponent1); // #29904.2 @@ -81,23 +186,76 @@ const fn62 = pipe( //// [genericFunctionInference1.js] -"use strict"; const f00 = pipe(list); const f01 = pipe(list, box); -const f02 = pipe(x => list(x), box); -const f03 = pipe(list, x => box(x)); -const f04 = pipe(x => list(x), x => box(x)); -const f05 = pipe(list, pipe(box)); -const f06 = pipe(x => list(x), pipe(box)); -const f07 = pipe(x => list(x), pipe(x => box(x))); -const f10 = pipe(list); -const f11 = pipe(list, box); -const f12 = pipe(x => list(x), box); -const f13 = pipe(list, x => box(x)); -const f14 = pipe(x => list(x), x => box(x)); -const f15 = pipe(list, pipe(box)); -const f16 = pipe(x => list(x), pipe(box)); -const f17 = pipe(x => list(x), pipe(x => box(x))); +const f02 = pipe(box, list); +const f03 = pipe(x => list(x), box); +const f04 = pipe(list, x => box(x)); +const f05 = pipe(x => list(x), x => box(x)); +const f06 = pipe(list, pipe(box)); +const f07 = pipe(x => list(x), pipe(box)); +const f08 = pipe(x => list(x), pipe(x => box(x))); +const f09 = pipe(list, x => x.length); +const f10 = pipe(foo); +const f11 = pipe(foo, foo); +const g00 = pipe(list); +const g01 = pipe(list, box); +const g02 = pipe(box, list); +const g03 = pipe(x => list(x), box); +const g04 = pipe(list, x => box(x)); +const g05 = pipe(x => list(x), x => box(x)); +const g06 = pipe(list, pipe(box)); +const g07 = pipe(x => list(x), pipe(box)); +const g08 = pipe(x => list(x), pipe(x => box(x))); +const g09 = pipe(list, x => x.length); +const g10 = pipe(foo); +const g12 = pipe(foo, foo); +const f20 = pipe2(list, box); +const f21 = pipe2(box, list); +const f22 = pipe2(list, list); +const f23 = pipe2(box, box); +const f24 = pipe2(f20, f20); +const f25 = pipe2(foo, foo); +const f26 = pipe2(f25, f25); +const f30 = pipe3(list, box); +const f31 = pipe3(box, list); +const f32 = pipe3(list, list); +const f40 = pipe4([list, box]); +const f41 = pipe4([box, list]); +const f50 = pipe5(list); // No higher order inference +// #417 +function mirror(f) { return f; } +var identityM = mirror(identity); +var x = 1; +var y = identity(x); +var z = identityM(x); +// #3038 +export function keyOf(value) { + return value.key; +} +var data = []; +toKeys(data, keyOf); // Error +// #9366 +function flip(f) { + return (b, a) => f(a, b); +} +function zip(x, y) { + return [x, y]; +} +var expected = flip(zip); +var actual = flip(zip); +// #9366 +const map = (transform) => (arr) => arr.map(transform); +const identityStr = (t) => t; +const arr = map(identityStr)(['a']); +const arr1 = map(identity)(['a']); +// #9949 +function of2(one, two) { + return [one, two]; +} +const flipped = flip(of2); +const enhance = pipe(myHoc1, myHoc2); +const MyComponent2 = enhance(MyComponent1); // #29904.2 const fn20 = pipe((_a) => 1); const fn30 = pipe(x => x + 1, x => x * 2); diff --git a/tests/baselines/reference/genericFunctionInference1.symbols b/tests/baselines/reference/genericFunctionInference1.symbols index d49a20cec9c8e..9ee085feae853 100644 --- a/tests/baselines/reference/genericFunctionInference1.symbols +++ b/tests/baselines/reference/genericFunctionInference1.symbols @@ -65,222 +65,691 @@ declare function box(x: V): { value: V }; >value : Symbol(value, Decl(genericFunctionInference1.ts, 5, 32)) >V : Symbol(V, Decl(genericFunctionInference1.ts, 5, 21)) +declare function foo(x: T): T; +>foo : Symbol(foo, Decl(genericFunctionInference1.ts, 5, 44)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 6, 21)) +>value : Symbol(value, Decl(genericFunctionInference1.ts, 6, 32)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 6, 21)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 6, 45)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 6, 21)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 6, 21)) + const f00 = pipe(list); ->f00 : Symbol(f00, Decl(genericFunctionInference1.ts, 7, 5)) +>f00 : Symbol(f00, Decl(genericFunctionInference1.ts, 8, 5)) >pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) >list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) const f01 = pipe(list, box); ->f01 : Symbol(f01, Decl(genericFunctionInference1.ts, 8, 5)) +>f01 : Symbol(f01, Decl(genericFunctionInference1.ts, 9, 5)) >pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) >list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) >box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) -const f02 = pipe(x => list(x), box); ->f02 : Symbol(f02, Decl(genericFunctionInference1.ts, 9, 5)) +const f02 = pipe(box, list); +>f02 : Symbol(f02, Decl(genericFunctionInference1.ts, 10, 5)) >pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) ->x : Symbol(x, Decl(genericFunctionInference1.ts, 9, 17)) ->list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) ->x : Symbol(x, Decl(genericFunctionInference1.ts, 9, 17)) >box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) - -const f03 = pipe(list, x => box(x)); ->f03 : Symbol(f03, Decl(genericFunctionInference1.ts, 10, 5)) ->pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) >list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) ->x : Symbol(x, Decl(genericFunctionInference1.ts, 10, 22)) ->box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) ->x : Symbol(x, Decl(genericFunctionInference1.ts, 10, 22)) -const f04 = pipe(x => list(x), x => box(x)) ->f04 : Symbol(f04, Decl(genericFunctionInference1.ts, 11, 5)) +const f03 = pipe(x => list(x), box); +>f03 : Symbol(f03, Decl(genericFunctionInference1.ts, 11, 5)) >pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) >x : Symbol(x, Decl(genericFunctionInference1.ts, 11, 17)) >list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) >x : Symbol(x, Decl(genericFunctionInference1.ts, 11, 17)) ->x : Symbol(x, Decl(genericFunctionInference1.ts, 11, 30)) >box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) ->x : Symbol(x, Decl(genericFunctionInference1.ts, 11, 30)) -const f05 = pipe(list, pipe(box)); ->f05 : Symbol(f05, Decl(genericFunctionInference1.ts, 12, 5)) +const f04 = pipe(list, x => box(x)); +>f04 : Symbol(f04, Decl(genericFunctionInference1.ts, 12, 5)) >pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) >list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) ->pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 12, 22)) >box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 12, 22)) -const f06 = pipe(x => list(x), pipe(box)); ->f06 : Symbol(f06, Decl(genericFunctionInference1.ts, 13, 5)) +const f05 = pipe(x => list(x), x => box(x)) +>f05 : Symbol(f05, Decl(genericFunctionInference1.ts, 13, 5)) >pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) >x : Symbol(x, Decl(genericFunctionInference1.ts, 13, 17)) >list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) >x : Symbol(x, Decl(genericFunctionInference1.ts, 13, 17)) ->pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 13, 30)) >box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 13, 30)) -const f07 = pipe(x => list(x), pipe(x => box(x))); ->f07 : Symbol(f07, Decl(genericFunctionInference1.ts, 14, 5)) +const f06 = pipe(list, pipe(box)); +>f06 : Symbol(f06, Decl(genericFunctionInference1.ts, 14, 5)) >pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) ->x : Symbol(x, Decl(genericFunctionInference1.ts, 14, 17)) >list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) ->x : Symbol(x, Decl(genericFunctionInference1.ts, 14, 17)) >pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) ->x : Symbol(x, Decl(genericFunctionInference1.ts, 14, 36)) >box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) ->x : Symbol(x, Decl(genericFunctionInference1.ts, 14, 36)) -const f10: (x: T) => T[] = pipe(list); ->f10 : Symbol(f10, Decl(genericFunctionInference1.ts, 16, 5)) ->T : Symbol(T, Decl(genericFunctionInference1.ts, 16, 12)) ->x : Symbol(x, Decl(genericFunctionInference1.ts, 16, 15)) ->T : Symbol(T, Decl(genericFunctionInference1.ts, 16, 12)) ->T : Symbol(T, Decl(genericFunctionInference1.ts, 16, 12)) +const f07 = pipe(x => list(x), pipe(box)); +>f07 : Symbol(f07, Decl(genericFunctionInference1.ts, 15, 5)) >pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 15, 17)) >list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) - -const f11: (x: T) => { value: T[] } = pipe(list, box); ->f11 : Symbol(f11, Decl(genericFunctionInference1.ts, 17, 5)) ->T : Symbol(T, Decl(genericFunctionInference1.ts, 17, 12)) ->x : Symbol(x, Decl(genericFunctionInference1.ts, 17, 15)) ->T : Symbol(T, Decl(genericFunctionInference1.ts, 17, 12)) ->value : Symbol(value, Decl(genericFunctionInference1.ts, 17, 25)) ->T : Symbol(T, Decl(genericFunctionInference1.ts, 17, 12)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 15, 17)) >pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) ->list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) >box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) -const f12: (x: T) => { value: T[] } = pipe(x => list(x), box); ->f12 : Symbol(f12, Decl(genericFunctionInference1.ts, 18, 5)) ->T : Symbol(T, Decl(genericFunctionInference1.ts, 18, 12)) ->x : Symbol(x, Decl(genericFunctionInference1.ts, 18, 15)) ->T : Symbol(T, Decl(genericFunctionInference1.ts, 18, 12)) ->value : Symbol(value, Decl(genericFunctionInference1.ts, 18, 25)) ->T : Symbol(T, Decl(genericFunctionInference1.ts, 18, 12)) +const f08 = pipe(x => list(x), pipe(x => box(x))); +>f08 : Symbol(f08, Decl(genericFunctionInference1.ts, 16, 5)) >pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) ->x : Symbol(x, Decl(genericFunctionInference1.ts, 18, 46)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 16, 17)) >list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) ->x : Symbol(x, Decl(genericFunctionInference1.ts, 18, 46)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 16, 17)) +>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 16, 36)) >box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 16, 36)) -const f13: (x: T) => { value: T[] } = pipe(list, x => box(x)); ->f13 : Symbol(f13, Decl(genericFunctionInference1.ts, 19, 5)) ->T : Symbol(T, Decl(genericFunctionInference1.ts, 19, 12)) ->x : Symbol(x, Decl(genericFunctionInference1.ts, 19, 15)) ->T : Symbol(T, Decl(genericFunctionInference1.ts, 19, 12)) ->value : Symbol(value, Decl(genericFunctionInference1.ts, 19, 25)) ->T : Symbol(T, Decl(genericFunctionInference1.ts, 19, 12)) +const f09 = pipe(list, x => x.length); +>f09 : Symbol(f09, Decl(genericFunctionInference1.ts, 17, 5)) >pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) >list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) ->x : Symbol(x, Decl(genericFunctionInference1.ts, 19, 51)) ->box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) ->x : Symbol(x, Decl(genericFunctionInference1.ts, 19, 51)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 17, 22)) +>x.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 17, 22)) +>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) -const f14: (x: T) => { value: T[] } = pipe(x => list(x), x => box(x)) ->f14 : Symbol(f14, Decl(genericFunctionInference1.ts, 20, 5)) ->T : Symbol(T, Decl(genericFunctionInference1.ts, 20, 12)) ->x : Symbol(x, Decl(genericFunctionInference1.ts, 20, 15)) ->T : Symbol(T, Decl(genericFunctionInference1.ts, 20, 12)) ->value : Symbol(value, Decl(genericFunctionInference1.ts, 20, 25)) ->T : Symbol(T, Decl(genericFunctionInference1.ts, 20, 12)) +const f10 = pipe(foo); +>f10 : Symbol(f10, Decl(genericFunctionInference1.ts, 18, 5)) >pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) ->x : Symbol(x, Decl(genericFunctionInference1.ts, 20, 46)) ->list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) ->x : Symbol(x, Decl(genericFunctionInference1.ts, 20, 46)) ->x : Symbol(x, Decl(genericFunctionInference1.ts, 20, 59)) ->box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) ->x : Symbol(x, Decl(genericFunctionInference1.ts, 20, 59)) +>foo : Symbol(foo, Decl(genericFunctionInference1.ts, 5, 44)) + +const f11 = pipe(foo, foo); +>f11 : Symbol(f11, Decl(genericFunctionInference1.ts, 19, 5)) +>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) +>foo : Symbol(foo, Decl(genericFunctionInference1.ts, 5, 44)) +>foo : Symbol(foo, Decl(genericFunctionInference1.ts, 5, 44)) -const f15: (x: T) => { value: T[] } = pipe(list, pipe(box)); ->f15 : Symbol(f15, Decl(genericFunctionInference1.ts, 21, 5)) +const g00: (x: T) => T[] = pipe(list); +>g00 : Symbol(g00, Decl(genericFunctionInference1.ts, 21, 5)) >T : Symbol(T, Decl(genericFunctionInference1.ts, 21, 12)) >x : Symbol(x, Decl(genericFunctionInference1.ts, 21, 15)) >T : Symbol(T, Decl(genericFunctionInference1.ts, 21, 12)) ->value : Symbol(value, Decl(genericFunctionInference1.ts, 21, 25)) >T : Symbol(T, Decl(genericFunctionInference1.ts, 21, 12)) >pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) >list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) ->pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) ->box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) -const f16: (x: T) => { value: T[] } = pipe(x => list(x), pipe(box)); ->f16 : Symbol(f16, Decl(genericFunctionInference1.ts, 22, 5)) +const g01: (x: T) => { value: T[] } = pipe(list, box); +>g01 : Symbol(g01, Decl(genericFunctionInference1.ts, 22, 5)) >T : Symbol(T, Decl(genericFunctionInference1.ts, 22, 12)) >x : Symbol(x, Decl(genericFunctionInference1.ts, 22, 15)) >T : Symbol(T, Decl(genericFunctionInference1.ts, 22, 12)) >value : Symbol(value, Decl(genericFunctionInference1.ts, 22, 25)) >T : Symbol(T, Decl(genericFunctionInference1.ts, 22, 12)) >pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) ->x : Symbol(x, Decl(genericFunctionInference1.ts, 22, 46)) >list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) ->x : Symbol(x, Decl(genericFunctionInference1.ts, 22, 46)) ->pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) >box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) -const f17: (x: T) => { value: T[] } = pipe(x => list(x), pipe(x => box(x))); ->f17 : Symbol(f17, Decl(genericFunctionInference1.ts, 23, 5)) +const g02: (x: T) => { value: T }[] = pipe(box, list); +>g02 : Symbol(g02, Decl(genericFunctionInference1.ts, 23, 5)) >T : Symbol(T, Decl(genericFunctionInference1.ts, 23, 12)) >x : Symbol(x, Decl(genericFunctionInference1.ts, 23, 15)) >T : Symbol(T, Decl(genericFunctionInference1.ts, 23, 12)) >value : Symbol(value, Decl(genericFunctionInference1.ts, 23, 25)) >T : Symbol(T, Decl(genericFunctionInference1.ts, 23, 12)) >pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) ->x : Symbol(x, Decl(genericFunctionInference1.ts, 23, 46)) +>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) +>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) + +const g03: (x: T) => { value: T[] } = pipe(x => list(x), box); +>g03 : Symbol(g03, Decl(genericFunctionInference1.ts, 24, 5)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 24, 12)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 24, 15)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 24, 12)) +>value : Symbol(value, Decl(genericFunctionInference1.ts, 24, 25)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 24, 12)) +>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 24, 46)) +>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 24, 46)) +>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) + +const g04: (x: T) => { value: T[] } = pipe(list, x => box(x)); +>g04 : Symbol(g04, Decl(genericFunctionInference1.ts, 25, 5)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 25, 12)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 25, 15)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 25, 12)) +>value : Symbol(value, Decl(genericFunctionInference1.ts, 25, 25)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 25, 12)) +>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) +>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 25, 51)) +>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 25, 51)) + +const g05: (x: T) => { value: T[] } = pipe(x => list(x), x => box(x)) +>g05 : Symbol(g05, Decl(genericFunctionInference1.ts, 26, 5)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 26, 12)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 26, 15)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 26, 12)) +>value : Symbol(value, Decl(genericFunctionInference1.ts, 26, 25)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 26, 12)) +>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 26, 46)) >list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) ->x : Symbol(x, Decl(genericFunctionInference1.ts, 23, 46)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 26, 46)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 26, 59)) +>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 26, 59)) + +const g06: (x: T) => { value: T[] } = pipe(list, pipe(box)); +>g06 : Symbol(g06, Decl(genericFunctionInference1.ts, 27, 5)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 27, 12)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 27, 15)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 27, 12)) +>value : Symbol(value, Decl(genericFunctionInference1.ts, 27, 25)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 27, 12)) +>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) +>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) +>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) +>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) + +const g07: (x: T) => { value: T[] } = pipe(x => list(x), pipe(box)); +>g07 : Symbol(g07, Decl(genericFunctionInference1.ts, 28, 5)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 28, 12)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 28, 15)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 28, 12)) +>value : Symbol(value, Decl(genericFunctionInference1.ts, 28, 25)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 28, 12)) +>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 28, 46)) +>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 28, 46)) >pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) ->x : Symbol(x, Decl(genericFunctionInference1.ts, 23, 65)) >box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) ->x : Symbol(x, Decl(genericFunctionInference1.ts, 23, 65)) + +const g08: (x: T) => { value: T[] } = pipe(x => list(x), pipe(x => box(x))); +>g08 : Symbol(g08, Decl(genericFunctionInference1.ts, 29, 5)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 29, 12)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 29, 15)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 29, 12)) +>value : Symbol(value, Decl(genericFunctionInference1.ts, 29, 25)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 29, 12)) +>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 29, 46)) +>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 29, 46)) +>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 29, 65)) +>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 29, 65)) + +const g09: (x: T) => number = pipe(list, x => x.length); +>g09 : Symbol(g09, Decl(genericFunctionInference1.ts, 30, 5)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 30, 12)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 30, 15)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 30, 12)) +>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) +>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 30, 43)) +>x.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 30, 43)) +>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) + +const g10: (x: T) => T = pipe(foo); +>g10 : Symbol(g10, Decl(genericFunctionInference1.ts, 31, 5)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 31, 12)) +>value : Symbol(value, Decl(genericFunctionInference1.ts, 31, 23)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 31, 12)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 31, 36)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 31, 12)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 31, 12)) +>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) +>foo : Symbol(foo, Decl(genericFunctionInference1.ts, 5, 44)) + +const g12: (x: T) => T = pipe(foo, foo); +>g12 : Symbol(g12, Decl(genericFunctionInference1.ts, 32, 5)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 32, 12)) +>value : Symbol(value, Decl(genericFunctionInference1.ts, 32, 23)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 32, 12)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 32, 36)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 32, 12)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 32, 12)) +>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) +>foo : Symbol(foo, Decl(genericFunctionInference1.ts, 5, 44)) +>foo : Symbol(foo, Decl(genericFunctionInference1.ts, 5, 44)) + +declare function pipe2(ab: (a: A) => B, cd: (c: C) => D): (a: [A, C]) => [B, D]; +>pipe2 : Symbol(pipe2, Decl(genericFunctionInference1.ts, 32, 64)) +>A : Symbol(A, Decl(genericFunctionInference1.ts, 34, 23)) +>B : Symbol(B, Decl(genericFunctionInference1.ts, 34, 25)) +>C : Symbol(C, Decl(genericFunctionInference1.ts, 34, 28)) +>D : Symbol(D, Decl(genericFunctionInference1.ts, 34, 31)) +>ab : Symbol(ab, Decl(genericFunctionInference1.ts, 34, 35)) +>a : Symbol(a, Decl(genericFunctionInference1.ts, 34, 40)) +>A : Symbol(A, Decl(genericFunctionInference1.ts, 34, 23)) +>B : Symbol(B, Decl(genericFunctionInference1.ts, 34, 25)) +>cd : Symbol(cd, Decl(genericFunctionInference1.ts, 34, 51)) +>c : Symbol(c, Decl(genericFunctionInference1.ts, 34, 57)) +>C : Symbol(C, Decl(genericFunctionInference1.ts, 34, 28)) +>D : Symbol(D, Decl(genericFunctionInference1.ts, 34, 31)) +>a : Symbol(a, Decl(genericFunctionInference1.ts, 34, 71)) +>A : Symbol(A, Decl(genericFunctionInference1.ts, 34, 23)) +>C : Symbol(C, Decl(genericFunctionInference1.ts, 34, 28)) +>B : Symbol(B, Decl(genericFunctionInference1.ts, 34, 25)) +>D : Symbol(D, Decl(genericFunctionInference1.ts, 34, 31)) + +const f20 = pipe2(list, box); +>f20 : Symbol(f20, Decl(genericFunctionInference1.ts, 36, 5)) +>pipe2 : Symbol(pipe2, Decl(genericFunctionInference1.ts, 32, 64)) +>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) +>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) + +const f21 = pipe2(box, list); +>f21 : Symbol(f21, Decl(genericFunctionInference1.ts, 37, 5)) +>pipe2 : Symbol(pipe2, Decl(genericFunctionInference1.ts, 32, 64)) +>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) +>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) + +const f22 = pipe2(list, list); +>f22 : Symbol(f22, Decl(genericFunctionInference1.ts, 38, 5)) +>pipe2 : Symbol(pipe2, Decl(genericFunctionInference1.ts, 32, 64)) +>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) +>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) + +const f23 = pipe2(box, box); +>f23 : Symbol(f23, Decl(genericFunctionInference1.ts, 39, 5)) +>pipe2 : Symbol(pipe2, Decl(genericFunctionInference1.ts, 32, 64)) +>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) +>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) + +const f24 = pipe2(f20, f20); +>f24 : Symbol(f24, Decl(genericFunctionInference1.ts, 40, 5)) +>pipe2 : Symbol(pipe2, Decl(genericFunctionInference1.ts, 32, 64)) +>f20 : Symbol(f20, Decl(genericFunctionInference1.ts, 36, 5)) +>f20 : Symbol(f20, Decl(genericFunctionInference1.ts, 36, 5)) + +const f25 = pipe2(foo, foo); +>f25 : Symbol(f25, Decl(genericFunctionInference1.ts, 41, 5)) +>pipe2 : Symbol(pipe2, Decl(genericFunctionInference1.ts, 32, 64)) +>foo : Symbol(foo, Decl(genericFunctionInference1.ts, 5, 44)) +>foo : Symbol(foo, Decl(genericFunctionInference1.ts, 5, 44)) + +const f26 = pipe2(f25, f25); +>f26 : Symbol(f26, Decl(genericFunctionInference1.ts, 42, 5)) +>pipe2 : Symbol(pipe2, Decl(genericFunctionInference1.ts, 32, 64)) +>f25 : Symbol(f25, Decl(genericFunctionInference1.ts, 41, 5)) +>f25 : Symbol(f25, Decl(genericFunctionInference1.ts, 41, 5)) + +declare function pipe3(ab: (a: A) => B, ac: (a: A) => C): (a: A) => [B, C]; +>pipe3 : Symbol(pipe3, Decl(genericFunctionInference1.ts, 42, 28)) +>A : Symbol(A, Decl(genericFunctionInference1.ts, 44, 23)) +>B : Symbol(B, Decl(genericFunctionInference1.ts, 44, 25)) +>C : Symbol(C, Decl(genericFunctionInference1.ts, 44, 28)) +>ab : Symbol(ab, Decl(genericFunctionInference1.ts, 44, 32)) +>a : Symbol(a, Decl(genericFunctionInference1.ts, 44, 37)) +>A : Symbol(A, Decl(genericFunctionInference1.ts, 44, 23)) +>B : Symbol(B, Decl(genericFunctionInference1.ts, 44, 25)) +>ac : Symbol(ac, Decl(genericFunctionInference1.ts, 44, 48)) +>a : Symbol(a, Decl(genericFunctionInference1.ts, 44, 54)) +>A : Symbol(A, Decl(genericFunctionInference1.ts, 44, 23)) +>C : Symbol(C, Decl(genericFunctionInference1.ts, 44, 28)) +>a : Symbol(a, Decl(genericFunctionInference1.ts, 44, 68)) +>A : Symbol(A, Decl(genericFunctionInference1.ts, 44, 23)) +>B : Symbol(B, Decl(genericFunctionInference1.ts, 44, 25)) +>C : Symbol(C, Decl(genericFunctionInference1.ts, 44, 28)) + +const f30 = pipe3(list, box); +>f30 : Symbol(f30, Decl(genericFunctionInference1.ts, 46, 5)) +>pipe3 : Symbol(pipe3, Decl(genericFunctionInference1.ts, 42, 28)) +>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) +>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) + +const f31 = pipe3(box, list); +>f31 : Symbol(f31, Decl(genericFunctionInference1.ts, 47, 5)) +>pipe3 : Symbol(pipe3, Decl(genericFunctionInference1.ts, 42, 28)) +>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) +>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) + +const f32 = pipe3(list, list); +>f32 : Symbol(f32, Decl(genericFunctionInference1.ts, 48, 5)) +>pipe3 : Symbol(pipe3, Decl(genericFunctionInference1.ts, 42, 28)) +>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) +>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) + +declare function pipe4(funcs: [(a: A) => B, (b: B) => C]): (a: A) => C; +>pipe4 : Symbol(pipe4, Decl(genericFunctionInference1.ts, 48, 30)) +>A : Symbol(A, Decl(genericFunctionInference1.ts, 50, 23)) +>B : Symbol(B, Decl(genericFunctionInference1.ts, 50, 25)) +>C : Symbol(C, Decl(genericFunctionInference1.ts, 50, 28)) +>funcs : Symbol(funcs, Decl(genericFunctionInference1.ts, 50, 32)) +>a : Symbol(a, Decl(genericFunctionInference1.ts, 50, 41)) +>A : Symbol(A, Decl(genericFunctionInference1.ts, 50, 23)) +>B : Symbol(B, Decl(genericFunctionInference1.ts, 50, 25)) +>b : Symbol(b, Decl(genericFunctionInference1.ts, 50, 54)) +>B : Symbol(B, Decl(genericFunctionInference1.ts, 50, 25)) +>C : Symbol(C, Decl(genericFunctionInference1.ts, 50, 28)) +>a : Symbol(a, Decl(genericFunctionInference1.ts, 50, 69)) +>A : Symbol(A, Decl(genericFunctionInference1.ts, 50, 23)) +>C : Symbol(C, Decl(genericFunctionInference1.ts, 50, 28)) + +const f40 = pipe4([list, box]); +>f40 : Symbol(f40, Decl(genericFunctionInference1.ts, 52, 5)) +>pipe4 : Symbol(pipe4, Decl(genericFunctionInference1.ts, 48, 30)) +>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) +>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) + +const f41 = pipe4([box, list]); +>f41 : Symbol(f41, Decl(genericFunctionInference1.ts, 53, 5)) +>pipe4 : Symbol(pipe4, Decl(genericFunctionInference1.ts, 48, 30)) +>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) +>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) + +declare function pipe5(f: (a: A) => B): { f: (a: A) => B }; +>pipe5 : Symbol(pipe5, Decl(genericFunctionInference1.ts, 53, 31)) +>A : Symbol(A, Decl(genericFunctionInference1.ts, 55, 23)) +>B : Symbol(B, Decl(genericFunctionInference1.ts, 55, 25)) +>f : Symbol(f, Decl(genericFunctionInference1.ts, 55, 29)) +>a : Symbol(a, Decl(genericFunctionInference1.ts, 55, 33)) +>A : Symbol(A, Decl(genericFunctionInference1.ts, 55, 23)) +>B : Symbol(B, Decl(genericFunctionInference1.ts, 55, 25)) +>f : Symbol(f, Decl(genericFunctionInference1.ts, 55, 47)) +>a : Symbol(a, Decl(genericFunctionInference1.ts, 55, 52)) +>A : Symbol(A, Decl(genericFunctionInference1.ts, 55, 23)) +>B : Symbol(B, Decl(genericFunctionInference1.ts, 55, 25)) + +const f50 = pipe5(list); // No higher order inference +>f50 : Symbol(f50, Decl(genericFunctionInference1.ts, 57, 5)) +>pipe5 : Symbol(pipe5, Decl(genericFunctionInference1.ts, 53, 31)) +>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) + +// #417 + +function mirror(f: (a: A) => B): (a: A) => B { return f; } +>mirror : Symbol(mirror, Decl(genericFunctionInference1.ts, 57, 24)) +>A : Symbol(A, Decl(genericFunctionInference1.ts, 61, 16)) +>B : Symbol(B, Decl(genericFunctionInference1.ts, 61, 18)) +>f : Symbol(f, Decl(genericFunctionInference1.ts, 61, 22)) +>a : Symbol(a, Decl(genericFunctionInference1.ts, 61, 26)) +>A : Symbol(A, Decl(genericFunctionInference1.ts, 61, 16)) +>B : Symbol(B, Decl(genericFunctionInference1.ts, 61, 18)) +>a : Symbol(a, Decl(genericFunctionInference1.ts, 61, 40)) +>A : Symbol(A, Decl(genericFunctionInference1.ts, 61, 16)) +>B : Symbol(B, Decl(genericFunctionInference1.ts, 61, 18)) +>f : Symbol(f, Decl(genericFunctionInference1.ts, 61, 22)) + +var identityM = mirror(identity); +>identityM : Symbol(identityM, Decl(genericFunctionInference1.ts, 62, 3)) +>mirror : Symbol(mirror, Decl(genericFunctionInference1.ts, 57, 24)) +>identity : Symbol(identity, Decl(genericFunctionInference1.ts, 154, 13)) + +var x = 1; +>x : Symbol(x, Decl(genericFunctionInference1.ts, 64, 3)) + +var y = identity(x); +>y : Symbol(y, Decl(genericFunctionInference1.ts, 65, 3)) +>identity : Symbol(identity, Decl(genericFunctionInference1.ts, 154, 13)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 64, 3)) + +var z = identityM(x); +>z : Symbol(z, Decl(genericFunctionInference1.ts, 66, 3)) +>identityM : Symbol(identityM, Decl(genericFunctionInference1.ts, 62, 3)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 64, 3)) + +// #3038 + +export function keyOf(value: { key: a; }): a { +>keyOf : Symbol(keyOf, Decl(genericFunctionInference1.ts, 66, 21)) +>a : Symbol(a, Decl(genericFunctionInference1.ts, 70, 22)) +>value : Symbol(value, Decl(genericFunctionInference1.ts, 70, 25)) +>key : Symbol(key, Decl(genericFunctionInference1.ts, 70, 33)) +>a : Symbol(a, Decl(genericFunctionInference1.ts, 70, 22)) +>a : Symbol(a, Decl(genericFunctionInference1.ts, 70, 22)) + + return value.key; +>value.key : Symbol(key, Decl(genericFunctionInference1.ts, 70, 33)) +>value : Symbol(value, Decl(genericFunctionInference1.ts, 70, 25)) +>key : Symbol(key, Decl(genericFunctionInference1.ts, 70, 33)) +} +export interface Data { +>Data : Symbol(Data, Decl(genericFunctionInference1.ts, 72, 1)) + + key: number; +>key : Symbol(Data.key, Decl(genericFunctionInference1.ts, 73, 23)) + + value: Date; +>value : Symbol(Data.value, Decl(genericFunctionInference1.ts, 74, 16)) +>Date : Symbol(Date, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.scripthost.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +} + +var data: Data[] = []; +>data : Symbol(data, Decl(genericFunctionInference1.ts, 78, 3)) +>Data : Symbol(Data, Decl(genericFunctionInference1.ts, 72, 1)) + +declare function toKeys(values: a[], toKey: (value: a) => string): string[]; +>toKeys : Symbol(toKeys, Decl(genericFunctionInference1.ts, 78, 22)) +>a : Symbol(a, Decl(genericFunctionInference1.ts, 80, 24)) +>values : Symbol(values, Decl(genericFunctionInference1.ts, 80, 27)) +>a : Symbol(a, Decl(genericFunctionInference1.ts, 80, 24)) +>toKey : Symbol(toKey, Decl(genericFunctionInference1.ts, 80, 39)) +>value : Symbol(value, Decl(genericFunctionInference1.ts, 80, 48)) +>a : Symbol(a, Decl(genericFunctionInference1.ts, 80, 24)) + +toKeys(data, keyOf); // Error +>toKeys : Symbol(toKeys, Decl(genericFunctionInference1.ts, 78, 22)) +>data : Symbol(data, Decl(genericFunctionInference1.ts, 78, 3)) +>keyOf : Symbol(keyOf, Decl(genericFunctionInference1.ts, 66, 21)) + +// #9366 + +function flip(f: (a: a, b: b) => c): (b: b, a: a) => c { +>flip : Symbol(flip, Decl(genericFunctionInference1.ts, 82, 20)) +>a : Symbol(a, Decl(genericFunctionInference1.ts, 86, 14)) +>b : Symbol(b, Decl(genericFunctionInference1.ts, 86, 16)) +>c : Symbol(c, Decl(genericFunctionInference1.ts, 86, 19)) +>f : Symbol(f, Decl(genericFunctionInference1.ts, 86, 23)) +>a : Symbol(a, Decl(genericFunctionInference1.ts, 86, 27)) +>a : Symbol(a, Decl(genericFunctionInference1.ts, 86, 14)) +>b : Symbol(b, Decl(genericFunctionInference1.ts, 86, 32)) +>b : Symbol(b, Decl(genericFunctionInference1.ts, 86, 16)) +>c : Symbol(c, Decl(genericFunctionInference1.ts, 86, 19)) +>b : Symbol(b, Decl(genericFunctionInference1.ts, 86, 47)) +>b : Symbol(b, Decl(genericFunctionInference1.ts, 86, 16)) +>a : Symbol(a, Decl(genericFunctionInference1.ts, 86, 52)) +>a : Symbol(a, Decl(genericFunctionInference1.ts, 86, 14)) +>c : Symbol(c, Decl(genericFunctionInference1.ts, 86, 19)) + + return (b: b, a: a) => f(a, b); +>b : Symbol(b, Decl(genericFunctionInference1.ts, 87, 10)) +>b : Symbol(b, Decl(genericFunctionInference1.ts, 86, 16)) +>a : Symbol(a, Decl(genericFunctionInference1.ts, 87, 15)) +>a : Symbol(a, Decl(genericFunctionInference1.ts, 86, 14)) +>f : Symbol(f, Decl(genericFunctionInference1.ts, 86, 23)) +>a : Symbol(a, Decl(genericFunctionInference1.ts, 87, 15)) +>b : Symbol(b, Decl(genericFunctionInference1.ts, 87, 10)) +} +function zip(x: T, y: U): [T, U] { +>zip : Symbol(zip, Decl(genericFunctionInference1.ts, 88, 1)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 89, 13)) +>U : Symbol(U, Decl(genericFunctionInference1.ts, 89, 15)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 89, 19)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 89, 13)) +>y : Symbol(y, Decl(genericFunctionInference1.ts, 89, 24)) +>U : Symbol(U, Decl(genericFunctionInference1.ts, 89, 15)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 89, 13)) +>U : Symbol(U, Decl(genericFunctionInference1.ts, 89, 15)) + + return [x, y]; +>x : Symbol(x, Decl(genericFunctionInference1.ts, 89, 19)) +>y : Symbol(y, Decl(genericFunctionInference1.ts, 89, 24)) +} + +var expected: (y: U, x: T) => [T, U] = flip(zip); +>expected : Symbol(expected, Decl(genericFunctionInference1.ts, 93, 3)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 93, 15)) +>U : Symbol(U, Decl(genericFunctionInference1.ts, 93, 17)) +>y : Symbol(y, Decl(genericFunctionInference1.ts, 93, 21)) +>U : Symbol(U, Decl(genericFunctionInference1.ts, 93, 17)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 93, 26)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 93, 15)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 93, 15)) +>U : Symbol(U, Decl(genericFunctionInference1.ts, 93, 17)) +>flip : Symbol(flip, Decl(genericFunctionInference1.ts, 82, 20)) +>zip : Symbol(zip, Decl(genericFunctionInference1.ts, 88, 1)) + +var actual = flip(zip); +>actual : Symbol(actual, Decl(genericFunctionInference1.ts, 94, 3)) +>flip : Symbol(flip, Decl(genericFunctionInference1.ts, 82, 20)) +>zip : Symbol(zip, Decl(genericFunctionInference1.ts, 88, 1)) + +// #9366 + +const map = (transform: (t: T) => U) => +>map : Symbol(map, Decl(genericFunctionInference1.ts, 98, 5)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 98, 13)) +>U : Symbol(U, Decl(genericFunctionInference1.ts, 98, 15)) +>transform : Symbol(transform, Decl(genericFunctionInference1.ts, 98, 19)) +>t : Symbol(t, Decl(genericFunctionInference1.ts, 98, 31)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 98, 13)) +>U : Symbol(U, Decl(genericFunctionInference1.ts, 98, 15)) + + (arr: T[]) => arr.map(transform) +>arr : Symbol(arr, Decl(genericFunctionInference1.ts, 99, 5)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 98, 13)) +>arr.map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --)) +>arr : Symbol(arr, Decl(genericFunctionInference1.ts, 99, 5)) +>map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --)) +>transform : Symbol(transform, Decl(genericFunctionInference1.ts, 98, 19)) + +const identityStr = (t: string) => t; +>identityStr : Symbol(identityStr, Decl(genericFunctionInference1.ts, 101, 5)) +>t : Symbol(t, Decl(genericFunctionInference1.ts, 101, 21)) +>t : Symbol(t, Decl(genericFunctionInference1.ts, 101, 21)) + +const arr: string[] = map(identityStr)(['a']); +>arr : Symbol(arr, Decl(genericFunctionInference1.ts, 103, 5)) +>map : Symbol(map, Decl(genericFunctionInference1.ts, 98, 5)) +>identityStr : Symbol(identityStr, Decl(genericFunctionInference1.ts, 101, 5)) + +const arr1: string[] = map(identity)(['a']); +>arr1 : Symbol(arr1, Decl(genericFunctionInference1.ts, 104, 5)) +>map : Symbol(map, Decl(genericFunctionInference1.ts, 98, 5)) +>identity : Symbol(identity, Decl(genericFunctionInference1.ts, 154, 13)) + +// #9949 + +function of2(one: a, two: b): [a, b] { +>of2 : Symbol(of2, Decl(genericFunctionInference1.ts, 104, 44)) +>a : Symbol(a, Decl(genericFunctionInference1.ts, 108, 13)) +>b : Symbol(b, Decl(genericFunctionInference1.ts, 108, 15)) +>one : Symbol(one, Decl(genericFunctionInference1.ts, 108, 19)) +>a : Symbol(a, Decl(genericFunctionInference1.ts, 108, 13)) +>two : Symbol(two, Decl(genericFunctionInference1.ts, 108, 26)) +>b : Symbol(b, Decl(genericFunctionInference1.ts, 108, 15)) +>a : Symbol(a, Decl(genericFunctionInference1.ts, 108, 13)) +>b : Symbol(b, Decl(genericFunctionInference1.ts, 108, 15)) + + return [one, two]; +>one : Symbol(one, Decl(genericFunctionInference1.ts, 108, 19)) +>two : Symbol(two, Decl(genericFunctionInference1.ts, 108, 26)) +} + +const flipped = flip(of2); +>flipped : Symbol(flipped, Decl(genericFunctionInference1.ts, 112, 5)) +>flip : Symbol(flip, Decl(genericFunctionInference1.ts, 82, 20)) +>of2 : Symbol(of2, Decl(genericFunctionInference1.ts, 104, 44)) + +// #29904.1 + +type Component

= (props: P) => {}; +>Component : Symbol(Component, Decl(genericFunctionInference1.ts, 112, 26)) +>P : Symbol(P, Decl(genericFunctionInference1.ts, 116, 15)) +>props : Symbol(props, Decl(genericFunctionInference1.ts, 116, 21)) +>P : Symbol(P, Decl(genericFunctionInference1.ts, 116, 15)) + +declare const myHoc1:

(C: Component

) => Component

; +>myHoc1 : Symbol(myHoc1, Decl(genericFunctionInference1.ts, 118, 13)) +>P : Symbol(P, Decl(genericFunctionInference1.ts, 118, 23)) +>C : Symbol(C, Decl(genericFunctionInference1.ts, 118, 26)) +>Component : Symbol(Component, Decl(genericFunctionInference1.ts, 112, 26)) +>P : Symbol(P, Decl(genericFunctionInference1.ts, 118, 23)) +>Component : Symbol(Component, Decl(genericFunctionInference1.ts, 112, 26)) +>P : Symbol(P, Decl(genericFunctionInference1.ts, 118, 23)) + +declare const myHoc2:

(C: Component

) => Component

; +>myHoc2 : Symbol(myHoc2, Decl(genericFunctionInference1.ts, 119, 13)) +>P : Symbol(P, Decl(genericFunctionInference1.ts, 119, 23)) +>C : Symbol(C, Decl(genericFunctionInference1.ts, 119, 26)) +>Component : Symbol(Component, Decl(genericFunctionInference1.ts, 112, 26)) +>P : Symbol(P, Decl(genericFunctionInference1.ts, 119, 23)) +>Component : Symbol(Component, Decl(genericFunctionInference1.ts, 112, 26)) +>P : Symbol(P, Decl(genericFunctionInference1.ts, 119, 23)) + +declare const MyComponent1: Component<{ foo: 1 }>; +>MyComponent1 : Symbol(MyComponent1, Decl(genericFunctionInference1.ts, 121, 13)) +>Component : Symbol(Component, Decl(genericFunctionInference1.ts, 112, 26)) +>foo : Symbol(foo, Decl(genericFunctionInference1.ts, 121, 39)) + +const enhance = pipe( +>enhance : Symbol(enhance, Decl(genericFunctionInference1.ts, 123, 5)) +>pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) + + myHoc1, +>myHoc1 : Symbol(myHoc1, Decl(genericFunctionInference1.ts, 118, 13)) + + myHoc2, +>myHoc2 : Symbol(myHoc2, Decl(genericFunctionInference1.ts, 119, 13)) + +); + +const MyComponent2 = enhance(MyComponent1); +>MyComponent2 : Symbol(MyComponent2, Decl(genericFunctionInference1.ts, 128, 5)) +>enhance : Symbol(enhance, Decl(genericFunctionInference1.ts, 123, 5)) +>MyComponent1 : Symbol(MyComponent1, Decl(genericFunctionInference1.ts, 121, 13)) // #29904.2 const fn20 = pipe((_a?: {}) => 1); ->fn20 : Symbol(fn20, Decl(genericFunctionInference1.ts, 27, 5)) +>fn20 : Symbol(fn20, Decl(genericFunctionInference1.ts, 132, 5)) >pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) ->_a : Symbol(_a, Decl(genericFunctionInference1.ts, 27, 19)) +>_a : Symbol(_a, Decl(genericFunctionInference1.ts, 132, 19)) // #29904.3 type Fn = (n: number) => number; ->Fn : Symbol(Fn, Decl(genericFunctionInference1.ts, 27, 34)) ->n : Symbol(n, Decl(genericFunctionInference1.ts, 31, 11)) +>Fn : Symbol(Fn, Decl(genericFunctionInference1.ts, 132, 34)) +>n : Symbol(n, Decl(genericFunctionInference1.ts, 136, 11)) const fn30: Fn = pipe( ->fn30 : Symbol(fn30, Decl(genericFunctionInference1.ts, 32, 5)) ->Fn : Symbol(Fn, Decl(genericFunctionInference1.ts, 27, 34)) +>fn30 : Symbol(fn30, Decl(genericFunctionInference1.ts, 137, 5)) +>Fn : Symbol(Fn, Decl(genericFunctionInference1.ts, 132, 34)) >pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) x => x + 1, ->x : Symbol(x, Decl(genericFunctionInference1.ts, 32, 22)) ->x : Symbol(x, Decl(genericFunctionInference1.ts, 32, 22)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 137, 22)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 137, 22)) x => x * 2, ->x : Symbol(x, Decl(genericFunctionInference1.ts, 33, 15)) ->x : Symbol(x, Decl(genericFunctionInference1.ts, 33, 15)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 138, 15)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 138, 15)) ); const promise = Promise.resolve(1); ->promise : Symbol(promise, Decl(genericFunctionInference1.ts, 37, 5)) +>promise : Symbol(promise, Decl(genericFunctionInference1.ts, 142, 5)) >Promise.resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) >resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) promise.then( >promise.then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) ->promise : Symbol(promise, Decl(genericFunctionInference1.ts, 37, 5)) +>promise : Symbol(promise, Decl(genericFunctionInference1.ts, 142, 5)) >then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) pipe( >pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) x => x + 1, ->x : Symbol(x, Decl(genericFunctionInference1.ts, 39, 9)) ->x : Symbol(x, Decl(genericFunctionInference1.ts, 39, 9)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 144, 9)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 144, 9)) x => x * 2, ->x : Symbol(x, Decl(genericFunctionInference1.ts, 40, 19)) ->x : Symbol(x, Decl(genericFunctionInference1.ts, 40, 19)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 145, 19)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 145, 19)) ), ); @@ -288,94 +757,94 @@ promise.then( // #29904.4 declare const getString: () => string; ->getString : Symbol(getString, Decl(genericFunctionInference1.ts, 47, 13)) +>getString : Symbol(getString, Decl(genericFunctionInference1.ts, 152, 13)) declare const orUndefined: (name: string) => string | undefined; ->orUndefined : Symbol(orUndefined, Decl(genericFunctionInference1.ts, 48, 13)) ->name : Symbol(name, Decl(genericFunctionInference1.ts, 48, 28)) +>orUndefined : Symbol(orUndefined, Decl(genericFunctionInference1.ts, 153, 13)) +>name : Symbol(name, Decl(genericFunctionInference1.ts, 153, 28)) declare const identity: (value: T) => T; ->identity : Symbol(identity, Decl(genericFunctionInference1.ts, 49, 13)) ->T : Symbol(T, Decl(genericFunctionInference1.ts, 49, 25)) ->value : Symbol(value, Decl(genericFunctionInference1.ts, 49, 28)) ->T : Symbol(T, Decl(genericFunctionInference1.ts, 49, 25)) ->T : Symbol(T, Decl(genericFunctionInference1.ts, 49, 25)) +>identity : Symbol(identity, Decl(genericFunctionInference1.ts, 154, 13)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 154, 25)) +>value : Symbol(value, Decl(genericFunctionInference1.ts, 154, 28)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 154, 25)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 154, 25)) const fn40 = pipe( ->fn40 : Symbol(fn40, Decl(genericFunctionInference1.ts, 51, 5)) +>fn40 : Symbol(fn40, Decl(genericFunctionInference1.ts, 156, 5)) >pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) getString, ->getString : Symbol(getString, Decl(genericFunctionInference1.ts, 47, 13)) +>getString : Symbol(getString, Decl(genericFunctionInference1.ts, 152, 13)) string => orUndefined(string), ->string : Symbol(string, Decl(genericFunctionInference1.ts, 52, 14)) ->orUndefined : Symbol(orUndefined, Decl(genericFunctionInference1.ts, 48, 13)) ->string : Symbol(string, Decl(genericFunctionInference1.ts, 52, 14)) +>string : Symbol(string, Decl(genericFunctionInference1.ts, 157, 14)) +>orUndefined : Symbol(orUndefined, Decl(genericFunctionInference1.ts, 153, 13)) +>string : Symbol(string, Decl(genericFunctionInference1.ts, 157, 14)) identity, ->identity : Symbol(identity, Decl(genericFunctionInference1.ts, 49, 13)) +>identity : Symbol(identity, Decl(genericFunctionInference1.ts, 154, 13)) ); // #29904.6 declare const getArray: () => string[]; ->getArray : Symbol(getArray, Decl(genericFunctionInference1.ts, 59, 13)) +>getArray : Symbol(getArray, Decl(genericFunctionInference1.ts, 164, 13)) declare const first: (ts: T[]) => T; ->first : Symbol(first, Decl(genericFunctionInference1.ts, 60, 13)) ->T : Symbol(T, Decl(genericFunctionInference1.ts, 60, 22)) ->ts : Symbol(ts, Decl(genericFunctionInference1.ts, 60, 25)) ->T : Symbol(T, Decl(genericFunctionInference1.ts, 60, 22)) ->T : Symbol(T, Decl(genericFunctionInference1.ts, 60, 22)) +>first : Symbol(first, Decl(genericFunctionInference1.ts, 165, 13)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 165, 22)) +>ts : Symbol(ts, Decl(genericFunctionInference1.ts, 165, 25)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 165, 22)) +>T : Symbol(T, Decl(genericFunctionInference1.ts, 165, 22)) const fn60 = pipe( ->fn60 : Symbol(fn60, Decl(genericFunctionInference1.ts, 62, 5)) +>fn60 : Symbol(fn60, Decl(genericFunctionInference1.ts, 167, 5)) >pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) getArray, ->getArray : Symbol(getArray, Decl(genericFunctionInference1.ts, 59, 13)) +>getArray : Symbol(getArray, Decl(genericFunctionInference1.ts, 164, 13)) x => x, ->x : Symbol(x, Decl(genericFunctionInference1.ts, 63, 13)) ->x : Symbol(x, Decl(genericFunctionInference1.ts, 63, 13)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 168, 13)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 168, 13)) first, ->first : Symbol(first, Decl(genericFunctionInference1.ts, 60, 13)) +>first : Symbol(first, Decl(genericFunctionInference1.ts, 165, 13)) ); const fn61 = pipe( ->fn61 : Symbol(fn61, Decl(genericFunctionInference1.ts, 68, 5)) +>fn61 : Symbol(fn61, Decl(genericFunctionInference1.ts, 173, 5)) >pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) getArray, ->getArray : Symbol(getArray, Decl(genericFunctionInference1.ts, 59, 13)) +>getArray : Symbol(getArray, Decl(genericFunctionInference1.ts, 164, 13)) identity, ->identity : Symbol(identity, Decl(genericFunctionInference1.ts, 49, 13)) +>identity : Symbol(identity, Decl(genericFunctionInference1.ts, 154, 13)) first, ->first : Symbol(first, Decl(genericFunctionInference1.ts, 60, 13)) +>first : Symbol(first, Decl(genericFunctionInference1.ts, 165, 13)) ); const fn62 = pipe( ->fn62 : Symbol(fn62, Decl(genericFunctionInference1.ts, 74, 5)) +>fn62 : Symbol(fn62, Decl(genericFunctionInference1.ts, 179, 5)) >pipe : Symbol(pipe, Decl(genericFunctionInference1.ts, 0, 0), Decl(genericFunctionInference1.ts, 0, 84), Decl(genericFunctionInference1.ts, 1, 104)) getArray, ->getArray : Symbol(getArray, Decl(genericFunctionInference1.ts, 59, 13)) +>getArray : Symbol(getArray, Decl(genericFunctionInference1.ts, 164, 13)) x => x, ->x : Symbol(x, Decl(genericFunctionInference1.ts, 75, 13)) ->x : Symbol(x, Decl(genericFunctionInference1.ts, 75, 13)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 180, 13)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 180, 13)) x => first(x), ->x : Symbol(x, Decl(genericFunctionInference1.ts, 76, 11)) ->first : Symbol(first, Decl(genericFunctionInference1.ts, 60, 13)) ->x : Symbol(x, Decl(genericFunctionInference1.ts, 76, 11)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 181, 11)) +>first : Symbol(first, Decl(genericFunctionInference1.ts, 165, 13)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 181, 11)) ); diff --git a/tests/baselines/reference/genericFunctionInference1.types b/tests/baselines/reference/genericFunctionInference1.types index cf85c1b5afb6c..e68b0ed6da0b5 100644 --- a/tests/baselines/reference/genericFunctionInference1.types +++ b/tests/baselines/reference/genericFunctionInference1.types @@ -32,6 +32,11 @@ declare function box(x: V): { value: V }; >x : V >value : V +declare function foo(x: T): T; +>foo : (x: T) => T +>value : T +>x : T + const f00 = pipe(list); >f00 : (a: T) => T[] >pipe(list) : (a: T) => T[] @@ -45,8 +50,15 @@ const f01 = pipe(list, box); >list : (a: T) => T[] >box : (x: V) => { value: V; } -const f02 = pipe(x => list(x), box); ->f02 : (x: any) => { value: any[]; } +const f02 = pipe(box, list); +>f02 : (x: V) => { value: V; }[] +>pipe(box, list) : (x: V) => { value: V; }[] +>pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } +>box : (x: V) => { value: V; } +>list : (a: T) => T[] + +const f03 = pipe(x => list(x), box); +>f03 : (x: any) => { value: any[]; } >pipe(x => list(x), box) : (x: any) => { value: any[]; } >pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } >x => list(x) : (x: any) => any[] @@ -56,8 +68,8 @@ const f02 = pipe(x => list(x), box); >x : any >box : (x: V) => { value: V; } -const f03 = pipe(list, x => box(x)); ->f03 : (a: T) => { value: T[]; } +const f04 = pipe(list, x => box(x)); +>f04 : (a: T) => { value: T[]; } >pipe(list, x => box(x)) : (a: T) => { value: T[]; } >pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } >list : (a: T) => T[] @@ -67,8 +79,8 @@ const f03 = pipe(list, x => box(x)); >box : (x: V) => { value: V; } >x : T[] -const f04 = pipe(x => list(x), x => box(x)) ->f04 : (x: any) => { value: any[]; } +const f05 = pipe(x => list(x), x => box(x)) +>f05 : (x: any) => { value: any[]; } >pipe(x => list(x), x => box(x)) : (x: any) => { value: any[]; } >pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } >x => list(x) : (x: any) => any[] @@ -82,8 +94,8 @@ const f04 = pipe(x => list(x), x => box(x)) >box : (x: V) => { value: V; } >x : any[] -const f05 = pipe(list, pipe(box)); ->f05 : (a: T) => { value: T[]; } +const f06 = pipe(list, pipe(box)); +>f06 : (a: T) => { value: T[]; } >pipe(list, pipe(box)) : (a: T) => { value: T[]; } >pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } >list : (a: T) => T[] @@ -91,8 +103,8 @@ const f05 = pipe(list, pipe(box)); >pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } >box : (x: V) => { value: V; } -const f06 = pipe(x => list(x), pipe(box)); ->f06 : (x: any) => { value: any[]; } +const f07 = pipe(x => list(x), pipe(box)); +>f07 : (x: any) => { value: any[]; } >pipe(x => list(x), pipe(box)) : (x: any) => { value: any[]; } >pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } >x => list(x) : (x: any) => any[] @@ -104,8 +116,8 @@ const f06 = pipe(x => list(x), pipe(box)); >pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } >box : (x: V) => { value: V; } -const f07 = pipe(x => list(x), pipe(x => box(x))); ->f07 : (x: any) => { value: any[]; } +const f08 = pipe(x => list(x), pipe(x => box(x))); +>f08 : (x: any) => { value: any[]; } >pipe(x => list(x), pipe(x => box(x))) : (x: any) => { value: any[]; } >pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } >x => list(x) : (x: any) => any[] @@ -121,15 +133,39 @@ const f07 = pipe(x => list(x), pipe(x => box(x))); >box : (x: V) => { value: V; } >x : any[] -const f10: (x: T) => T[] = pipe(list); ->f10 : (x: T) => T[] +const f09 = pipe(list, x => x.length); +>f09 : (a: T) => number +>pipe(list, x => x.length) : (a: T) => number +>pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } +>list : (a: T) => T[] +>x => x.length : (x: T[]) => number +>x : T[] +>x.length : number +>x : T[] +>length : number + +const f10 = pipe(foo); +>f10 : (x: T) => T +>pipe(foo) : (x: T) => T +>pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } +>foo : (x: T) => T + +const f11 = pipe(foo, foo); +>f11 : (x: T) => T +>pipe(foo, foo) : (x: T) => T +>pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } +>foo : (x: T) => T +>foo : (x: T) => T + +const g00: (x: T) => T[] = pipe(list); +>g00 : (x: T) => T[] >x : T >pipe(list) : (a: T) => T[] >pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } >list : (a: T) => T[] -const f11: (x: T) => { value: T[] } = pipe(list, box); ->f11 : (x: T) => { value: T[]; } +const g01: (x: T) => { value: T[] } = pipe(list, box); +>g01 : (x: T) => { value: T[]; } >x : T >value : T[] >pipe(list, box) : (a: T) => { value: T[]; } @@ -137,8 +173,17 @@ const f11: (x: T) => { value: T[] } = pipe(list, box); >list : (a: T) => T[] >box : (x: V) => { value: V; } -const f12: (x: T) => { value: T[] } = pipe(x => list(x), box); ->f12 : (x: T) => { value: T[]; } +const g02: (x: T) => { value: T }[] = pipe(box, list); +>g02 : (x: T) => { value: T; }[] +>x : T +>value : T +>pipe(box, list) : (x: T) => { value: T; }[] +>pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } +>box : (x: V) => { value: V; } +>list : (a: T) => T[] + +const g03: (x: T) => { value: T[] } = pipe(x => list(x), box); +>g03 : (x: T) => { value: T[]; } >x : T >value : T[] >pipe(x => list(x), box) : (x: T) => { value: T[]; } @@ -150,8 +195,8 @@ const f12: (x: T) => { value: T[] } = pipe(x => list(x), box); >x : T >box : (x: V) => { value: V; } -const f13: (x: T) => { value: T[] } = pipe(list, x => box(x)); ->f13 : (x: T) => { value: T[]; } +const g04: (x: T) => { value: T[] } = pipe(list, x => box(x)); +>g04 : (x: T) => { value: T[]; } >x : T >value : T[] >pipe(list, x => box(x)) : (a: T) => { value: T[]; } @@ -163,8 +208,8 @@ const f13: (x: T) => { value: T[] } = pipe(list, x => box(x)); >box : (x: V) => { value: V; } >x : T[] -const f14: (x: T) => { value: T[] } = pipe(x => list(x), x => box(x)) ->f14 : (x: T) => { value: T[]; } +const g05: (x: T) => { value: T[] } = pipe(x => list(x), x => box(x)) +>g05 : (x: T) => { value: T[]; } >x : T >value : T[] >pipe(x => list(x), x => box(x)) : (x: T) => { value: T[]; } @@ -180,8 +225,8 @@ const f14: (x: T) => { value: T[] } = pipe(x => list(x), x => box(x)) >box : (x: V) => { value: V; } >x : T[] -const f15: (x: T) => { value: T[] } = pipe(list, pipe(box)); ->f15 : (x: T) => { value: T[]; } +const g06: (x: T) => { value: T[] } = pipe(list, pipe(box)); +>g06 : (x: T) => { value: T[]; } >x : T >value : T[] >pipe(list, pipe(box)) : (a: T) => { value: T[]; } @@ -191,8 +236,8 @@ const f15: (x: T) => { value: T[] } = pipe(list, pipe(box)); >pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } >box : (x: V) => { value: V; } -const f16: (x: T) => { value: T[] } = pipe(x => list(x), pipe(box)); ->f16 : (x: T) => { value: T[]; } +const g07: (x: T) => { value: T[] } = pipe(x => list(x), pipe(box)); +>g07 : (x: T) => { value: T[]; } >x : T >value : T[] >pipe(x => list(x), pipe(box)) : (x: T) => { value: T[]; } @@ -206,8 +251,8 @@ const f16: (x: T) => { value: T[] } = pipe(x => list(x), pipe(box)); >pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } >box : (x: V) => { value: V; } -const f17: (x: T) => { value: T[] } = pipe(x => list(x), pipe(x => box(x))); ->f17 : (x: T) => { value: T[]; } +const g08: (x: T) => { value: T[] } = pipe(x => list(x), pipe(x => box(x))); +>g08 : (x: T) => { value: T[]; } >x : T >value : T[] >pipe(x => list(x), pipe(x => box(x))) : (x: T) => { value: T[]; } @@ -225,6 +270,365 @@ const f17: (x: T) => { value: T[] } = pipe(x => list(x), pipe(x => box(x))); >box : (x: V) => { value: V; } >x : T[] +const g09: (x: T) => number = pipe(list, x => x.length); +>g09 : (x: T) => number +>x : T +>pipe(list, x => x.length) : (a: T) => number +>pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } +>list : (a: T) => T[] +>x => x.length : (x: T[]) => number +>x : T[] +>x.length : number +>x : T[] +>length : number + +const g10: (x: T) => T = pipe(foo); +>g10 : (x: T) => T +>value : T +>x : T +>pipe(foo) : (x: T) => T +>pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } +>foo : (x: T) => T + +const g12: (x: T) => T = pipe(foo, foo); +>g12 : (x: T) => T +>value : T +>x : T +>pipe(foo, foo) : (x: T) => T +>pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } +>foo : (x: T) => T +>foo : (x: T) => T + +declare function pipe2(ab: (a: A) => B, cd: (c: C) => D): (a: [A, C]) => [B, D]; +>pipe2 : (ab: (a: A) => B, cd: (c: C) => D) => (a: [A, C]) => [B, D] +>ab : (a: A) => B +>a : A +>cd : (c: C) => D +>c : C +>a : [A, C] + +const f20 = pipe2(list, box); +>f20 : (a: [T, V]) => [T[], { value: V; }] +>pipe2(list, box) : (a: [T, V]) => [T[], { value: V; }] +>pipe2 : (ab: (a: A) => B, cd: (c: C) => D) => (a: [A, C]) => [B, D] +>list : (a: T) => T[] +>box : (x: V) => { value: V; } + +const f21 = pipe2(box, list); +>f21 : (a: [V, T]) => [{ value: V; }, T[]] +>pipe2(box, list) : (a: [V, T]) => [{ value: V; }, T[]] +>pipe2 : (ab: (a: A) => B, cd: (c: C) => D) => (a: [A, C]) => [B, D] +>box : (x: V) => { value: V; } +>list : (a: T) => T[] + +const f22 = pipe2(list, list); +>f22 : (a: [T, T1]) => [T[], T1[]] +>pipe2(list, list) : (a: [T, T1]) => [T[], T1[]] +>pipe2 : (ab: (a: A) => B, cd: (c: C) => D) => (a: [A, C]) => [B, D] +>list : (a: T) => T[] +>list : (a: T) => T[] + +const f23 = pipe2(box, box); +>f23 : (a: [V, V1]) => [{ value: V; }, { value: V1; }] +>pipe2(box, box) : (a: [V, V1]) => [{ value: V; }, { value: V1; }] +>pipe2 : (ab: (a: A) => B, cd: (c: C) => D) => (a: [A, C]) => [B, D] +>box : (x: V) => { value: V; } +>box : (x: V) => { value: V; } + +const f24 = pipe2(f20, f20); +>f24 : (a: [[T, V], [T1, V1]]) => [[T[], { value: V; }], [T1[], { value: V1; }]] +>pipe2(f20, f20) : (a: [[T, V], [T1, V1]]) => [[T[], { value: V; }], [T1[], { value: V1; }]] +>pipe2 : (ab: (a: A) => B, cd: (c: C) => D) => (a: [A, C]) => [B, D] +>f20 : (a: [T, V]) => [T[], { value: V; }] +>f20 : (a: [T, V]) => [T[], { value: V; }] + +const f25 = pipe2(foo, foo); +>f25 : (a: [T, T1]) => [T, T1] +>pipe2(foo, foo) : (a: [T, T1]) => [T, T1] +>pipe2 : (ab: (a: A) => B, cd: (c: C) => D) => (a: [A, C]) => [B, D] +>foo : (x: T) => T +>foo : (x: T) => T + +const f26 = pipe2(f25, f25); +>f26 : (a: [[T, T1], [T2, T3]]) => [[T, T1], [T2, T3]] +>pipe2(f25, f25) : (a: [[T, T1], [T2, T3]]) => [[T, T1], [T2, T3]] +>pipe2 : (ab: (a: A) => B, cd: (c: C) => D) => (a: [A, C]) => [B, D] +>f25 : (a: [T, T1]) => [T, T1] +>f25 : (a: [T, T1]) => [T, T1] + +declare function pipe3(ab: (a: A) => B, ac: (a: A) => C): (a: A) => [B, C]; +>pipe3 : (ab: (a: A) => B, ac: (a: A) => C) => (a: A) => [B, C] +>ab : (a: A) => B +>a : A +>ac : (a: A) => C +>a : A +>a : A + +const f30 = pipe3(list, box); +>f30 : (a: T) => [T[], { value: T; }] +>pipe3(list, box) : (a: T) => [T[], { value: T; }] +>pipe3 : (ab: (a: A) => B, ac: (a: A) => C) => (a: A) => [B, C] +>list : (a: T) => T[] +>box : (x: V) => { value: V; } + +const f31 = pipe3(box, list); +>f31 : (a: V) => [{ value: V; }, V[]] +>pipe3(box, list) : (a: V) => [{ value: V; }, V[]] +>pipe3 : (ab: (a: A) => B, ac: (a: A) => C) => (a: A) => [B, C] +>box : (x: V) => { value: V; } +>list : (a: T) => T[] + +const f32 = pipe3(list, list); +>f32 : (a: T) => [T[], T[]] +>pipe3(list, list) : (a: T) => [T[], T[]] +>pipe3 : (ab: (a: A) => B, ac: (a: A) => C) => (a: A) => [B, C] +>list : (a: T) => T[] +>list : (a: T) => T[] + +declare function pipe4(funcs: [(a: A) => B, (b: B) => C]): (a: A) => C; +>pipe4 : (funcs: [(a: A) => B, (b: B) => C]) => (a: A) => C +>funcs : [(a: A) => B, (b: B) => C] +>a : A +>b : B +>a : A + +const f40 = pipe4([list, box]); +>f40 : (a: T) => { value: T[]; } +>pipe4([list, box]) : (a: T) => { value: T[]; } +>pipe4 : (funcs: [(a: A) => B, (b: B) => C]) => (a: A) => C +>[list, box] : [(a: T) => T[], (x: V) => { value: V; }] +>list : (a: T) => T[] +>box : (x: V) => { value: V; } + +const f41 = pipe4([box, list]); +>f41 : (a: V) => { value: V; }[] +>pipe4([box, list]) : (a: V) => { value: V; }[] +>pipe4 : (funcs: [(a: A) => B, (b: B) => C]) => (a: A) => C +>[box, list] : [(x: V) => { value: V; }, (a: T) => T[]] +>box : (x: V) => { value: V; } +>list : (a: T) => T[] + +declare function pipe5(f: (a: A) => B): { f: (a: A) => B }; +>pipe5 : (f: (a: A) => B) => { f: (a: A) => B; } +>f : (a: A) => B +>a : A +>f : (a: A) => B +>a : A + +const f50 = pipe5(list); // No higher order inference +>f50 : { f: (a: {}) => {}[]; } +>pipe5(list) : { f: (a: {}) => {}[]; } +>pipe5 : (f: (a: A) => B) => { f: (a: A) => B; } +>list : (a: T) => T[] + +// #417 + +function mirror(f: (a: A) => B): (a: A) => B { return f; } +>mirror : (f: (a: A) => B) => (a: A) => B +>f : (a: A) => B +>a : A +>a : A +>f : (a: A) => B + +var identityM = mirror(identity); +>identityM : (a: T) => T +>mirror(identity) : (a: T) => T +>mirror : (f: (a: A) => B) => (a: A) => B +>identity : (value: T) => T + +var x = 1; +>x : number +>1 : 1 + +var y = identity(x); +>y : number +>identity(x) : number +>identity : (value: T) => T +>x : number + +var z = identityM(x); +>z : number +>identityM(x) : number +>identityM : (a: T) => T +>x : number + +// #3038 + +export function keyOf(value: { key: a; }): a { +>keyOf : (value: { key: a; }) => a +>value : { key: a; } +>key : a + + return value.key; +>value.key : a +>value : { key: a; } +>key : a +} +export interface Data { + key: number; +>key : number + + value: Date; +>value : Date +} + +var data: Data[] = []; +>data : Data[] +>[] : never[] + +declare function toKeys(values: a[], toKey: (value: a) => string): string[]; +>toKeys : (values: a[], toKey: (value: a) => string) => string[] +>values : a[] +>toKey : (value: a) => string +>value : a + +toKeys(data, keyOf); // Error +>toKeys(data, keyOf) : any +>toKeys : (values: a[], toKey: (value: a) => string) => string[] +>data : Data[] +>keyOf : (value: { key: a; }) => a + +// #9366 + +function flip(f: (a: a, b: b) => c): (b: b, a: a) => c { +>flip : (f: (a: a, b: b) => c) => (b: b, a: a) => c +>f : (a: a, b: b) => c +>a : a +>b : b +>b : b +>a : a + + return (b: b, a: a) => f(a, b); +>(b: b, a: a) => f(a, b) : (b: b, a: a) => c +>b : b +>a : a +>f(a, b) : c +>f : (a: a, b: b) => c +>a : a +>b : b +} +function zip(x: T, y: U): [T, U] { +>zip : (x: T, y: U) => [T, U] +>x : T +>y : U + + return [x, y]; +>[x, y] : [T, U] +>x : T +>y : U +} + +var expected: (y: U, x: T) => [T, U] = flip(zip); +>expected : (y: U, x: T) => [T, U] +>y : U +>x : T +>flip(zip) : (b: U, a: T) => [T, U] +>flip : (f: (a: a, b: b) => c) => (b: b, a: a) => c +>zip : (x: T, y: U) => [T, U] + +var actual = flip(zip); +>actual : (b: U, a: T) => [T, U] +>flip(zip) : (b: U, a: T) => [T, U] +>flip : (f: (a: a, b: b) => c) => (b: b, a: a) => c +>zip : (x: T, y: U) => [T, U] + +// #9366 + +const map = (transform: (t: T) => U) => +>map : (transform: (t: T) => U) => (arr: T[]) => U[] +>(transform: (t: T) => U) => (arr: T[]) => arr.map(transform) : (transform: (t: T) => U) => (arr: T[]) => U[] +>transform : (t: T) => U +>t : T + + (arr: T[]) => arr.map(transform) +>(arr: T[]) => arr.map(transform) : (arr: T[]) => U[] +>arr : T[] +>arr.map(transform) : U[] +>arr.map : (callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any) => U[] +>arr : T[] +>map : (callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any) => U[] +>transform : (t: T) => U + +const identityStr = (t: string) => t; +>identityStr : (t: string) => string +>(t: string) => t : (t: string) => string +>t : string +>t : string + +const arr: string[] = map(identityStr)(['a']); +>arr : string[] +>map(identityStr)(['a']) : string[] +>map(identityStr) : (arr: string[]) => string[] +>map : (transform: (t: T) => U) => (arr: T[]) => U[] +>identityStr : (t: string) => string +>['a'] : string[] +>'a' : "a" + +const arr1: string[] = map(identity)(['a']); +>arr1 : string[] +>map(identity)(['a']) : string[] +>map(identity) : (arr: T[]) => T[] +>map : (transform: (t: T) => U) => (arr: T[]) => U[] +>identity : (value: T) => T +>['a'] : string[] +>'a' : "a" + +// #9949 + +function of2(one: a, two: b): [a, b] { +>of2 : (one: a, two: b) => [a, b] +>one : a +>two : b + + return [one, two]; +>[one, two] : [a, b] +>one : a +>two : b +} + +const flipped = flip(of2); +>flipped : (b: b, a: a) => [a, b] +>flip(of2) : (b: b, a: a) => [a, b] +>flip : (f: (a: a, b: b) => c) => (b: b, a: a) => c +>of2 : (one: a, two: b) => [a, b] + +// #29904.1 + +type Component

= (props: P) => {}; +>Component : Component

+>props : P + +declare const myHoc1:

(C: Component

) => Component

; +>myHoc1 :

(C: Component

) => Component

+>C : Component

+ +declare const myHoc2:

(C: Component

) => Component

; +>myHoc2 :

(C: Component

) => Component

+>C : Component

+ +declare const MyComponent1: Component<{ foo: 1 }>; +>MyComponent1 : Component<{ foo: 1; }> +>foo : 1 + +const enhance = pipe( +>enhance :

(C: Component

) => Component

+>pipe( myHoc1, myHoc2,) :

(C: Component

) => Component

+>pipe : { (ab: (...args: A) => B): (...args: A) => B; (ab: (...args: A) => B, bc: (b: B) => C): (...args: A) => C; (ab: (...args: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...args: A) => D; } + + myHoc1, +>myHoc1 :

(C: Component

) => Component

+ + myHoc2, +>myHoc2 :

(C: Component

) => Component

+ +); + +const MyComponent2 = enhance(MyComponent1); +>MyComponent2 : Component<{ foo: 1; }> +>enhance(MyComponent1) : Component<{ foo: 1; }> +>enhance :

(C: Component

) => Component

+>MyComponent1 : Component<{ foo: 1; }> + // #29904.2 const fn20 = pipe((_a?: {}) => 1); From bf326aaabf48e7b72ae68b4a10d33ee23cee97e8 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 4 Mar 2019 11:15:09 -0800 Subject: [PATCH 13/19] Fix lint error --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9ca8b60d36a83..4493b9e00a37c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -23451,7 +23451,7 @@ namespace ts { } function getUniqueTypeParameters(context: InferenceContext, typeParameters: ReadonlyArray): ReadonlyArray { - let result: TypeParameter[] = []; + const result: TypeParameter[] = []; let oldTypeParameters: TypeParameter[] | undefined; let newTypeParameters: TypeParameter[] | undefined; for (const tp of typeParameters) { From ad823daabba75c8d6d77ab5f9194ce5feaa1fa96 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 5 Mar 2019 06:09:54 -0800 Subject: [PATCH 14/19] Consistently defer generic functions to second type inference pass --- src/compiler/checker.ts | 27 +++++++++++++++++++-------- src/compiler/types.ts | 1 + 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4493b9e00a37c..8cceb85a19a86 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -20138,7 +20138,7 @@ namespace ts { const paramType = getTypeAtPosition(signature, i); // For context sensitive arguments we pass the identityMapper, which is a signal to treat all // context sensitive function expressions as wildcards - const checkMode = (excludeArgument && excludeArgument[i] ? CheckMode.SkipContextSensitive : 0) | + const checkMode = (excludeArgument && i < excludeArgument.length && excludeArgument[i] ? CheckMode.SkipContextSensitive : 0) | (excludeArgument ? CheckMode.SkipGenericFunctions : 0); const argType = checkExpressionWithContextualType(arg, paramType, context, checkMode); inferTypes(context.inferences, argType, paramType); @@ -20241,7 +20241,7 @@ namespace ts { // However "context" and "updater" are implicit and can't be specify by users. Only the first parameter, props, // can be specified by users through attributes property. const paramType = getEffectiveFirstArgumentForJsxSignature(signature, node); - const checkMode = excludeArgument && excludeArgument[0] ? CheckMode.SkipContextSensitive : 0; + const checkMode = excludeArgument && excludeArgument.length > 0 && excludeArgument[0] ? CheckMode.SkipContextSensitive : 0; const attributesType = checkExpressionWithContextualType(node.attributes, paramType, /*contextualMapper*/ undefined, checkMode); return checkTypeRelatedToAndOptionallyElaborate(attributesType, paramType, relation, reportErrors ? node.tagName : undefined, node.attributes); } @@ -20276,13 +20276,13 @@ namespace ts { const arg = args[i]; if (arg.kind !== SyntaxKind.OmittedExpression) { const paramType = getTypeAtPosition(signature, i); - const checkMode = (excludeArgument && excludeArgument[i] ? CheckMode.SkipContextSensitive : 0) | + const checkMode = (excludeArgument && i < excludeArgument.length && excludeArgument[i] ? CheckMode.SkipContextSensitive : 0) | (excludeArgument ? CheckMode.SkipGenericFunctions : 0); const argType = checkExpressionWithContextualType(arg, paramType, /*contextualMapper*/ undefined, checkMode); // If one or more arguments are still excluded (as indicated by a non-null excludeArgument parameter), // we obtain the regular type of any object literal arguments because we may not have inferred complete // parameter types yet and therefore excess property checks may yield false positives (see #17041). - const checkArgType = excludeArgument ? getRegularTypeOfObjectLiteral(argType) : argType; + const checkArgType = excludeArgument && excludeArgument.length ? getRegularTypeOfObjectLiteral(argType) : argType; if (!checkTypeRelatedToAndOptionallyElaborate(checkArgType, paramType, relation, reportErrors ? arg : undefined, arg, headMessage)) { return false; } @@ -20665,7 +20665,7 @@ namespace ts { } else { inferenceContext = createInferenceContext(candidate.typeParameters, candidate, /*flags*/ isInJSFile(node) ? InferenceFlags.AnyDefault : InferenceFlags.None); - typeArgumentTypes = inferTypeArguments(node, candidate, args, excludeArgument, inferenceContext); + typeArgumentTypes = inferTypeArguments(node, candidate, args, excludeArgument || emptyArray, inferenceContext); } checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, isInJSFile(candidate.declaration), inferenceContext && inferenceContext.inferredTypeParameters); // If the original signature has a generic rest type, instantiation may produce a @@ -20678,14 +20678,14 @@ namespace ts { else { checkCandidate = candidate; } - if (!checkApplicableSignature(node, args, checkCandidate, relation, excludeArgument, /*reportErrors*/ false)) { + if (!checkApplicableSignature(node, args, checkCandidate, relation, excludeArgument || inferenceContext && emptyArray, /*reportErrors*/ false)) { // Give preference to error candidates that have no rest parameters (as they are more specific) if (!candidateForArgumentError || getEffectiveRestType(candidateForArgumentError) || !getEffectiveRestType(checkCandidate)) { candidateForArgumentError = checkCandidate; } continue; } - if (excludeArgument) { + if (excludeArgument || inferenceContext && inferenceContext.flags & InferenceFlags.SkippedGenericFunction) { // If one or more context sensitive arguments were excluded, we start including // them now (and keeping do so for any subsequent candidates) and perform a second // round of type inference and applicability checking for this particular candidate. @@ -20830,7 +20830,7 @@ namespace ts { function inferSignatureInstantiationForOverloadFailure(node: CallLikeExpression, typeParameters: ReadonlyArray, candidate: Signature, args: ReadonlyArray): Signature { const inferenceContext = createInferenceContext(typeParameters, candidate, /*flags*/ isInJSFile(node) ? InferenceFlags.AnyDefault : InferenceFlags.None); - const typeArgumentTypes = inferTypeArguments(node, candidate, args, getExcludeArgument(args), inferenceContext); + const typeArgumentTypes = inferTypeArguments(node, candidate, args, getExcludeArgument(args) || emptyArray, inferenceContext); return createSignatureInstantiation(candidate, typeArgumentTypes); } @@ -20932,6 +20932,7 @@ namespace ts { // sensitive arguments are being deferred) and every call signature is generic and returns a function type, // we return resolvingSignature here. This result will be propagated out and turned into anyFunctionType. if (checkMode & CheckMode.SkipGenericFunctions && callSignatures.every(isGenericFunctionReturningFunction)) { + skippedGenericFunction(node, checkMode); return resolvingSignature; } // If the function is explicitly marked with `@class`, then it must be constructed. @@ -23387,6 +23388,7 @@ namespace ts { const signature = getSingleCallSignature(type); if (signature && signature.typeParameters) { if (checkMode & CheckMode.SkipGenericFunctions) { + skippedGenericFunction(node, checkMode); return anyFunctionType; } const contextualType = getApparentTypeOfContextualType(node); @@ -23429,6 +23431,15 @@ namespace ts { return type; } + function skippedGenericFunction(node: Node, checkMode: CheckMode) { + if (checkMode & CheckMode.Inferential) { + // We have skipped a generic function during inferential typing. Obtain the inference context and + // indicate this has occurred such that we know a second pass of inference is be needed. + const context = getContextualMapper(node); + context.flags |= InferenceFlags.SkippedGenericFunction; + } + } + function hasInferenceCandidates(info: InferenceInfo) { return !!(info.candidates || info.contraCandidates); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 5217dd66fb494..0d24db8454eb0 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -4362,6 +4362,7 @@ namespace ts { NoDefault = 1 << 0, // Infer unknownType for no inferences (otherwise anyType or emptyObjectType) AnyDefault = 1 << 1, // Infer anyType for no inferences (otherwise emptyObjectType) NoFixing = 1 << 2, // Disable type parameter fixing + SkippedGenericFunction = 1 << 3, } /** From cde94441d31543f414bbeb70a6700d30ee7fbc39 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 5 Mar 2019 06:10:21 -0800 Subject: [PATCH 15/19] Accept new baselines --- tests/baselines/reference/genericRestParameters1.js | 2 +- tests/baselines/reference/genericRestParameters1.types | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/baselines/reference/genericRestParameters1.js b/tests/baselines/reference/genericRestParameters1.js index 3d8703213ac79..2932f2b96cbcd 100644 --- a/tests/baselines/reference/genericRestParameters1.js +++ b/tests/baselines/reference/genericRestParameters1.js @@ -309,7 +309,7 @@ declare function f16(a: A, b: B): A | B; declare let x20: number; declare let x21: string; declare let x22: string | number; -declare let x23: unknown; +declare let x23: string | number; declare let x24: string | number; declare let x30: string; declare let x31: string | number; diff --git a/tests/baselines/reference/genericRestParameters1.types b/tests/baselines/reference/genericRestParameters1.types index 497561c8a98bf..c9067b38c974d 100644 --- a/tests/baselines/reference/genericRestParameters1.types +++ b/tests/baselines/reference/genericRestParameters1.types @@ -462,8 +462,8 @@ let x22 = call(f15, "hello", 42); // string | number >42 : 42 let x23 = call(f16, "hello", 42); // unknown ->x23 : unknown ->call(f16, "hello", 42) : unknown +>x23 : string | number +>call(f16, "hello", 42) : string | number >call : (f: (...args: T) => U, ...args: T) => U >f16 : (a: A, b: B) => A | B >"hello" : "hello" From 6c790c02d9b7ed76f29989e8390d52d295c5d78c Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 5 Mar 2019 12:42:54 -0800 Subject: [PATCH 16/19] Remove unnecessary excludeArgument array and getExcludeArgument function --- src/compiler/checker.ts | 66 ++++++++++++----------------------------- 1 file changed, 19 insertions(+), 47 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8cceb85a19a86..ad6b87daa1aca 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -20068,15 +20068,14 @@ namespace ts { return getSignatureInstantiation(signature, getInferredTypes(context), isInJSFile(contextualSignature.declaration)); } - function inferJsxTypeArguments(node: JsxOpeningLikeElement, signature: Signature, excludeArgument: ReadonlyArray | undefined, context: InferenceContext): Type[] { + function inferJsxTypeArguments(node: JsxOpeningLikeElement, signature: Signature, checkMode: CheckMode, context: InferenceContext): Type[] { const paramType = getEffectiveFirstArgumentForJsxSignature(signature, node); - const checkMode = excludeArgument && excludeArgument[0] ? CheckMode.SkipContextSensitive : 0; const checkAttrType = checkExpressionWithContextualType(node.attributes, paramType, context, checkMode); inferTypes(context.inferences, checkAttrType, paramType); return getInferredTypes(context); } - function inferTypeArguments(node: CallLikeExpression, signature: Signature, args: ReadonlyArray, excludeArgument: ReadonlyArray | undefined, context: InferenceContext): Type[] { + function inferTypeArguments(node: CallLikeExpression, signature: Signature, args: ReadonlyArray, checkMode: CheckMode, context: InferenceContext): Type[] { // Clear out all the inference results from the last time inferTypeArguments was called on this context for (const inference of context.inferences) { // As an optimization, we don't have to clear (and later recompute) inferred types @@ -20089,7 +20088,7 @@ namespace ts { } if (isJsxOpeningLikeElement(node)) { - return inferJsxTypeArguments(node, signature, excludeArgument, context); + return inferJsxTypeArguments(node, signature, checkMode, context); } // If a contextual type is available, infer from that type to the return type of the call expression. For @@ -20136,10 +20135,6 @@ namespace ts { const arg = args[i]; if (arg.kind !== SyntaxKind.OmittedExpression) { const paramType = getTypeAtPosition(signature, i); - // For context sensitive arguments we pass the identityMapper, which is a signal to treat all - // context sensitive function expressions as wildcards - const checkMode = (excludeArgument && i < excludeArgument.length && excludeArgument[i] ? CheckMode.SkipContextSensitive : 0) | - (excludeArgument ? CheckMode.SkipGenericFunctions : 0); const argType = checkExpressionWithContextualType(arg, paramType, context, checkMode); inferTypes(context.inferences, argType, paramType); } @@ -20234,14 +20229,12 @@ namespace ts { * @param node a JSX opening-like element we are trying to figure its call signature * @param signature a candidate signature we are trying whether it is a call signature * @param relation a relationship to check parameter and argument type - * @param excludeArgument */ - function checkApplicableSignatureForJsxOpeningLikeElement(node: JsxOpeningLikeElement, signature: Signature, relation: Map, excludeArgument: boolean[] | undefined, reportErrors: boolean) { + function checkApplicableSignatureForJsxOpeningLikeElement(node: JsxOpeningLikeElement, signature: Signature, relation: Map, checkMode: CheckMode, reportErrors: boolean) { // Stateless function components can have maximum of three arguments: "props", "context", and "updater". // However "context" and "updater" are implicit and can't be specify by users. Only the first parameter, props, // can be specified by users through attributes property. const paramType = getEffectiveFirstArgumentForJsxSignature(signature, node); - const checkMode = excludeArgument && excludeArgument.length > 0 && excludeArgument[0] ? CheckMode.SkipContextSensitive : 0; const attributesType = checkExpressionWithContextualType(node.attributes, paramType, /*contextualMapper*/ undefined, checkMode); return checkTypeRelatedToAndOptionallyElaborate(attributesType, paramType, relation, reportErrors ? node.tagName : undefined, node.attributes); } @@ -20251,10 +20244,10 @@ namespace ts { args: ReadonlyArray, signature: Signature, relation: Map, - excludeArgument: boolean[] | undefined, + checkMode: CheckMode, reportErrors: boolean) { if (isJsxOpeningLikeElement(node)) { - return checkApplicableSignatureForJsxOpeningLikeElement(node, signature, relation, excludeArgument, reportErrors); + return checkApplicableSignatureForJsxOpeningLikeElement(node, signature, relation, checkMode, reportErrors); } const thisType = getThisTypeOfSignature(signature); if (thisType && thisType !== voidType && node.kind !== SyntaxKind.NewExpression) { @@ -20276,13 +20269,11 @@ namespace ts { const arg = args[i]; if (arg.kind !== SyntaxKind.OmittedExpression) { const paramType = getTypeAtPosition(signature, i); - const checkMode = (excludeArgument && i < excludeArgument.length && excludeArgument[i] ? CheckMode.SkipContextSensitive : 0) | - (excludeArgument ? CheckMode.SkipGenericFunctions : 0); const argType = checkExpressionWithContextualType(arg, paramType, /*contextualMapper*/ undefined, checkMode); - // If one or more arguments are still excluded (as indicated by a non-null excludeArgument parameter), + // If one or more arguments are still excluded (as indicated by CheckMode.SkipContextSensitive), // we obtain the regular type of any object literal arguments because we may not have inferred complete // parameter types yet and therefore excess property checks may yield false positives (see #17041). - const checkArgType = excludeArgument && excludeArgument.length ? getRegularTypeOfObjectLiteral(argType) : argType; + const checkArgType = checkMode & CheckMode.SkipContextSensitive ? getRegularTypeOfObjectLiteral(argType) : argType; if (!checkTypeRelatedToAndOptionallyElaborate(checkArgType, paramType, relation, reportErrors ? arg : undefined, arg, headMessage)) { return false; } @@ -20540,7 +20531,7 @@ namespace ts { // For a decorator, no arguments are susceptible to contextual typing due to the fact // decorators are applied to a declaration by the emitter, and not to an expression. const isSingleNonGenericCandidate = candidates.length === 1 && !candidates[0].typeParameters; - let excludeArgument = !isDecorator && !isSingleNonGenericCandidate ? getExcludeArgument(args) : undefined; + let argCheckMode = !isDecorator && !isSingleNonGenericCandidate && some(args, isContextSensitive) ? CheckMode.SkipContextSensitive : CheckMode.Normal; // The following variables are captured and modified by calls to chooseOverload. // If overload resolution or type argument inference fails, we want to report the @@ -20599,12 +20590,7 @@ namespace ts { // skip the checkApplicableSignature check. if (reportErrors) { if (candidateForArgumentError) { - // excludeArgument is undefined, in this case also equivalent to [undefined, undefined, ...] - // The importance of excludeArgument is to prevent us from typing function expression parameters - // in arguments too early. If possible, we'd like to only type them once we know the correct - // overload. However, this matters for the case where the call is correct. When the call is - // an error, we don't need to exclude any arguments, although it would cause no harm to do so. - checkApplicableSignature(node, args, candidateForArgumentError, assignableRelation, /*excludeArgument*/ undefined, /*reportErrors*/ true); + checkApplicableSignature(node, args, candidateForArgumentError, assignableRelation, CheckMode.Normal, /*reportErrors*/ true); } else if (candidateForArgumentArityError) { diagnostics.add(getArgumentArityError(node, [candidateForArgumentArityError], args)); @@ -20638,7 +20624,7 @@ namespace ts { if (typeArguments || !hasCorrectArity(node, args, candidate, signatureHelpTrailingComma)) { return undefined; } - if (!checkApplicableSignature(node, args, candidate, relation, excludeArgument, /*reportErrors*/ false)) { + if (!checkApplicableSignature(node, args, candidate, relation, CheckMode.Normal, /*reportErrors*/ false)) { candidateForArgumentError = candidate; return undefined; } @@ -20665,7 +20651,8 @@ namespace ts { } else { inferenceContext = createInferenceContext(candidate.typeParameters, candidate, /*flags*/ isInJSFile(node) ? InferenceFlags.AnyDefault : InferenceFlags.None); - typeArgumentTypes = inferTypeArguments(node, candidate, args, excludeArgument || emptyArray, inferenceContext); + typeArgumentTypes = inferTypeArguments(node, candidate, args, argCheckMode | CheckMode.SkipGenericFunctions, inferenceContext); + argCheckMode |= inferenceContext.flags & InferenceFlags.SkippedGenericFunction ? CheckMode.SkipGenericFunctions : CheckMode.Normal; } checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, isInJSFile(candidate.declaration), inferenceContext && inferenceContext.inferredTypeParameters); // If the original signature has a generic rest type, instantiation may produce a @@ -20678,20 +20665,20 @@ namespace ts { else { checkCandidate = candidate; } - if (!checkApplicableSignature(node, args, checkCandidate, relation, excludeArgument || inferenceContext && emptyArray, /*reportErrors*/ false)) { + if (!checkApplicableSignature(node, args, checkCandidate, relation, argCheckMode, /*reportErrors*/ false)) { // Give preference to error candidates that have no rest parameters (as they are more specific) if (!candidateForArgumentError || getEffectiveRestType(candidateForArgumentError) || !getEffectiveRestType(checkCandidate)) { candidateForArgumentError = checkCandidate; } continue; } - if (excludeArgument || inferenceContext && inferenceContext.flags & InferenceFlags.SkippedGenericFunction) { + if (argCheckMode) { // If one or more context sensitive arguments were excluded, we start including // them now (and keeping do so for any subsequent candidates) and perform a second // round of type inference and applicability checking for this particular candidate. - excludeArgument = undefined; + argCheckMode = CheckMode.Normal; if (inferenceContext) { - const typeArgumentTypes = inferTypeArguments(node, candidate, args, excludeArgument, inferenceContext); + const typeArgumentTypes = inferTypeArguments(node, candidate, args, argCheckMode, inferenceContext); checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, isInJSFile(candidate.declaration), inferenceContext && inferenceContext.inferredTypeParameters); // If the original signature has a generic rest type, instantiation may produce a // signature with different arity and we need to perform another arity check. @@ -20700,7 +20687,7 @@ namespace ts { continue; } } - if (!checkApplicableSignature(node, args, checkCandidate, relation, excludeArgument, /*reportErrors*/ false)) { + if (!checkApplicableSignature(node, args, checkCandidate, relation, argCheckMode, /*reportErrors*/ false)) { // Give preference to error candidates that have no rest parameters (as they are more specific) if (!candidateForArgumentError || getEffectiveRestType(candidateForArgumentError) || !getEffectiveRestType(checkCandidate)) { candidateForArgumentError = checkCandidate; @@ -20716,21 +20703,6 @@ namespace ts { } } - function getExcludeArgument(args: ReadonlyArray): boolean[] | undefined { - let excludeArgument: boolean[] | undefined; - // We do not need to call `getEffectiveArgumentCount` here as it only - // applies when calculating the number of arguments for a decorator. - for (let i = 0; i < args.length; i++) { - if (isContextSensitive(args[i])) { - if (!excludeArgument) { - excludeArgument = new Array(args.length); - } - excludeArgument[i] = true; - } - } - return excludeArgument; - } - // No signature was applicable. We have already reported the errors for the invalid signature. // If this is a type resolution session, e.g. Language Service, try to get better information than anySignature. function getCandidateForOverloadFailure( @@ -20830,7 +20802,7 @@ namespace ts { function inferSignatureInstantiationForOverloadFailure(node: CallLikeExpression, typeParameters: ReadonlyArray, candidate: Signature, args: ReadonlyArray): Signature { const inferenceContext = createInferenceContext(typeParameters, candidate, /*flags*/ isInJSFile(node) ? InferenceFlags.AnyDefault : InferenceFlags.None); - const typeArgumentTypes = inferTypeArguments(node, candidate, args, getExcludeArgument(args) || emptyArray, inferenceContext); + const typeArgumentTypes = inferTypeArguments(node, candidate, args, CheckMode.SkipContextSensitive | CheckMode.SkipGenericFunctions, inferenceContext); return createSignatureInstantiation(candidate, typeArgumentTypes); } From 6d882513ea8cc33dadab87eccbdaff8475ae218a Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 5 Mar 2019 17:45:09 -0800 Subject: [PATCH 17/19] Minor change to heuristic for deferring generic calls --- src/compiler/checker.ts | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ad6b87daa1aca..c6a866582a4f8 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -20900,10 +20900,19 @@ namespace ts { } return resolveErrorCall(node); } - // If we are skipping generic functions (i.e. this call is an argument to another call for which context - // sensitive arguments are being deferred) and every call signature is generic and returns a function type, - // we return resolvingSignature here. This result will be propagated out and turned into anyFunctionType. - if (checkMode & CheckMode.SkipGenericFunctions && callSignatures.every(isGenericFunctionReturningFunction)) { + // When a call to a generic function is an argument to an outer call to a generic function for which + // inference is in process, we have a choice to make. If the inner call relies on inferences made from + // its contextual type to its return type, deferring the inner call processing allows the best possible + // contextual type to accumulate. But if the outer call relies on inferences made from the return type of + // the inner call, the inner call should be processed early. There's no sure way to know which choice is + // right (only a full unification algorithm can determine that), so we resort to the following heuristic: + // If no type arguments are specified in the inner call and at least one call signature is generic and + // returns a function type, we choose to defer processing. This narrowly permits function composition + // operators to flow inferences through return types, but otherwise processes calls right away. We + // use the resolvingSignature singleton to indicate that we deferred processing. This result will be + // propagated out and eventually turned into silentNeverType (a type that is assignable to anything and + // from which we never make inferences). + if (checkMode & CheckMode.SkipGenericFunctions && !node.typeArguments && callSignatures.some(isGenericFunctionReturningFunction)) { skippedGenericFunction(node, checkMode); return resolvingSignature; } @@ -21385,7 +21394,7 @@ namespace ts { if (signature === resolvingSignature) { // CheckMode.SkipGenericFunctions is enabled and this is a call to a generic function that // returns a function type. We defer checking and return anyFunctionType. - return anyFunctionType; + return silentNeverType; } if (node.expression.kind === SyntaxKind.SuperKeyword) { From b34fe67ac53a59172111a81b60692cf6e27c51e8 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 5 Mar 2019 17:49:58 -0800 Subject: [PATCH 18/19] Fix issue of more inferences leading to worse results --- src/services/services.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/services.ts b/src/services/services.ts index 622c9de7ba3ea..7f5772d1489e4 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1798,7 +1798,7 @@ namespace ts { const span = createTextSpanFromBounds(start, end); const formatContext = formatting.getFormatContext(formatOptions); - return flatMap(deduplicate(errorCodes, equateValues, compareValues), errorCode => { + return flatMap(deduplicate(errorCodes, equateValues, compareValues), errorCode => { cancellationToken.throwIfCancellationRequested(); return codefix.getFixes({ errorCode, sourceFile, span, program, host, cancellationToken, formatContext, preferences }); }); From a9e924b6f0edb02c719a77f6d11fbae4704574e7 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 7 Mar 2019 07:06:48 -0800 Subject: [PATCH 19/19] Fix check for function type (allow checked type to have overloads) --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index c6a866582a4f8..3fa4868820101 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -20925,7 +20925,7 @@ namespace ts { } function isGenericFunctionReturningFunction(signature: Signature) { - return !!(signature.typeParameters && getSingleCallSignature(getReturnTypeOfSignature(signature))); + return !!(signature.typeParameters && isFunctionType(getReturnTypeOfSignature(signature))); } /**