diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9b59cb3574d18..3fa4868820101 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; } @@ -688,10 +688,12 @@ 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 + SkipGenericFunctions = 1 << 3, // Skip single signature generic functions + IsForSignatureHelp = 1 << 4, // Call resolution for purposes of signature help } const enum CallbackCheck { @@ -3981,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 @@ -8373,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); @@ -8389,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); } @@ -20035,7 +20052,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); @@ -20046,16 +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 checkAttrType = checkExpressionWithContextualType(node.attributes, paramType, excludeArgument && excludeArgument[0] !== undefined ? identityMapper : context); + 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 @@ -20068,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 @@ -20115,10 +20135,7 @@ 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 mapper = excludeArgument && excludeArgument[i] !== undefined ? identityMapper : context; - const argType = checkExpressionWithContextualType(arg, paramType, mapper); + const argType = checkExpressionWithContextualType(arg, paramType, context, checkMode); inferTypes(context.inferences, argType, paramType); } } @@ -20146,7 +20163,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; @@ -20154,7 +20171,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; } @@ -20212,14 +20229,13 @@ 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 attributesType = checkExpressionWithContextualType(node.attributes, paramType, excludeArgument && excludeArgument[0] ? identityMapper : undefined); + const attributesType = checkExpressionWithContextualType(node.attributes, paramType, /*contextualMapper*/ undefined, checkMode); return checkTypeRelatedToAndOptionallyElaborate(attributesType, paramType, relation, reportErrors ? node.tagName : undefined, node.attributes); } @@ -20228,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) { @@ -20253,11 +20269,11 @@ 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); - // If one or more arguments are still excluded (as indicated by a non-null excludeArgument parameter), + const argType = checkExpressionWithContextualType(arg, paramType, /*contextualMapper*/ undefined, checkMode); + // 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 ? getRegularTypeOfObjectLiteral(argType) : argType; + const checkArgType = checkMode & CheckMode.SkipContextSensitive ? getRegularTypeOfObjectLiteral(argType) : argType; if (!checkTypeRelatedToAndOptionallyElaborate(checkArgType, paramType, relation, reportErrors ? arg : undefined, arg, headMessage)) { return false; } @@ -20473,7 +20489,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); @@ -20515,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 @@ -20546,7 +20562,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 @@ -20574,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)); @@ -20613,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; } @@ -20640,9 +20651,10 @@ 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, argCheckMode | CheckMode.SkipGenericFunctions, inferenceContext); + argCheckMode |= inferenceContext.flags & InferenceFlags.SkippedGenericFunction ? CheckMode.SkipGenericFunctions : CheckMode.Normal; } - 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)) { @@ -20653,21 +20665,21 @@ namespace ts { else { checkCandidate = candidate; } - 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; } continue; } - if (excludeArgument) { + 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); - checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, isInJSFile(candidate.declaration)); + 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. if (getNonArrayRestType(candidate) && !hasCorrectArity(node, args, checkCandidate, signatureHelpTrailingComma)) { @@ -20675,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; @@ -20691,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( @@ -20805,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), inferenceContext); + const typeArgumentTypes = inferTypeArguments(node, candidate, args, CheckMode.SkipContextSensitive | CheckMode.SkipGenericFunctions, inferenceContext); return createSignatureInstantiation(candidate, typeArgumentTypes); } @@ -20828,7 +20825,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)) { @@ -20843,7 +20840,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); @@ -20903,12 +20900,32 @@ namespace ts { } return resolveErrorCall(node); } + // 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; + } // 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 && isFunctionType(getReturnTypeOfSignature(signature))); } /** @@ -20922,7 +20939,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) { @@ -20975,7 +20992,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 @@ -20984,7 +21001,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); @@ -21094,7 +21111,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); @@ -21115,7 +21132,7 @@ namespace ts { return resolveErrorCall(node); } - return resolveCall(node, callSignatures, candidatesOutArray, isForSignatureHelp); + return resolveCall(node, callSignatures, candidatesOutArray, checkMode); } /** @@ -21146,7 +21163,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) { @@ -21175,7 +21192,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 { @@ -21204,11 +21221,11 @@ 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); - 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); @@ -21228,7 +21245,7 @@ namespace ts { return resolveErrorCall(node); } - return resolveCall(node, signatures, candidatesOutArray, isForSignatureHelp); + return resolveCall(node, signatures, candidatesOutArray, checkMode); } /** @@ -21243,19 +21260,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."); } @@ -21267,7 +21284,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, @@ -21278,11 +21295,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; } @@ -21366,10 +21387,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 silentNeverType; + } if (node.expression.kind === SyntaxKind.SuperKeyword) { return voidType; @@ -21870,7 +21896,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 @@ -22060,7 +22086,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.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 @@ -22160,7 +22186,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); @@ -22200,7 +22226,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 ? @@ -23211,15 +23237,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. @@ -23233,7 +23257,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 @@ -23341,22 +23365,127 @@ namespace ts { } function instantiateTypeWithSingleGenericCallSignature(node: Expression | MethodDeclaration | QualifiedName, type: Type, checkMode?: CheckMode) { - if (checkMode === CheckMode.Inferential) { + if (checkMode && checkMode & (CheckMode.Inferential | CheckMode.SkipGenericFunctions)) { const signature = getSingleCallSignature(type); if (signature && signature.typeParameters) { + if (checkMode & CheckMode.SkipGenericFunctions) { + skippedGenericFunction(node, checkMode); + return anyFunctionType; + } const contextualType = getApparentTypeOfContextualType(node); 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)); } } } } - 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); + } + + 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 { + const result: TypeParameter[] = []; + let oldTypeParameters: TypeParameter[] | undefined; + let newTypeParameters: TypeParameter[] | undefined; + for (const tp of typeParameters) { + const name = tp.symbol.escapedName; + 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); + 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 hasTypeParameterByName(typeParameters: ReadonlyArray | undefined, name: __String) { + return some(typeParameters, tp => tp.symbol.escapedName === name); + } + + 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; + } + } + } + /** * 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. @@ -23496,7 +23625,7 @@ namespace ts { } /* falls through */ case SyntaxKind.NewExpression: - return checkCallExpression(node); + return checkCallExpression(node, checkMode); case SyntaxKind.TaggedTemplateExpression: return checkTaggedTemplateExpression(node); case SyntaxKind.ParenthesizedExpression: diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 42fd1126d4cba..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, } /** @@ -4391,6 +4392,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 */ 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 }); }); 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.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 new file mode 100644 index 0000000000000..4e89f9c0795e5 --- /dev/null +++ b/tests/baselines/reference/genericFunctionInference1.js @@ -0,0 +1,267 @@ +//// [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 }; +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 + +// #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), +); + + +//// [genericFunctionInference1.js] +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 = 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); +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..9ee085feae853 --- /dev/null +++ b/tests/baselines/reference/genericFunctionInference1.symbols @@ -0,0 +1,850 @@ +=== 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)) + +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, 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, 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(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)) +>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) +>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) + +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)) +>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) + +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)) +>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 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)) +>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 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)) +>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 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)) +>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)) +>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) + +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, 16, 17)) +>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) +>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 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, 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 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)) +>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 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)) +>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)) + +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)) +>list : Symbol(list, Decl(genericFunctionInference1.ts, 2, 124)) +>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) + +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)) +>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, 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)) +>box : Symbol(box, Decl(genericFunctionInference1.ts, 4, 36)) + +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, 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, 132, 19)) + +// #29904.3 + +type Fn = (n: number) => number; +>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, 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, 137, 22)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 137, 22)) + + x => x * 2, +>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, 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, 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, 144, 9)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 144, 9)) + + x => x * 2, +>x : Symbol(x, Decl(genericFunctionInference1.ts, 145, 19)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 145, 19)) + + ), +); + +// #29904.4 + +declare const getString: () => string; +>getString : Symbol(getString, Decl(genericFunctionInference1.ts, 152, 13)) + +declare const orUndefined: (name: string) => string | undefined; +>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, 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, 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, 152, 13)) + + string => orUndefined(string), +>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, 154, 13)) + +); + +// #29904.6 + +declare const getArray: () => string[]; +>getArray : Symbol(getArray, Decl(genericFunctionInference1.ts, 164, 13)) + +declare const first: (ts: T[]) => T; +>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, 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, 164, 13)) + + x => x, +>x : Symbol(x, Decl(genericFunctionInference1.ts, 168, 13)) +>x : Symbol(x, Decl(genericFunctionInference1.ts, 168, 13)) + + first, +>first : Symbol(first, Decl(genericFunctionInference1.ts, 165, 13)) + +); + +const fn61 = pipe( +>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, 164, 13)) + + identity, +>identity : Symbol(identity, Decl(genericFunctionInference1.ts, 154, 13)) + + first, +>first : Symbol(first, Decl(genericFunctionInference1.ts, 165, 13)) + +); + +const fn62 = pipe( +>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, 164, 13)) + + x => x, +>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, 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 new file mode 100644 index 0000000000000..e68b0ed6da0b5 --- /dev/null +++ b/tests/baselines/reference/genericFunctionInference1.types @@ -0,0 +1,801 @@ +=== 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 + +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[] +>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: 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 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[] +>x : any +>list(x) : any[] +>list : (a: T) => T[] +>x : any +>box : (x: V) => { value: V; } + +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[] +>x => box(x) : (x: T[]) => { value: T[]; } +>x : T[] +>box(x) : { value: T[]; } +>box : (x: V) => { value: V; } +>x : T[] + +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[] +>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 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[] +>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 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[] +>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 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[] +>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 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 g01: (x: T) => { value: T[] } = pipe(list, box); +>g01 : (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 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[]; } +>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 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[]; } +>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 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[]; } +>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 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[]; } +>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 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[]; } +>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 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[]; } +>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[] + +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); +>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[] + +); + 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" 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[] } diff --git a/tests/cases/compiler/genericFunctionInference1.ts b/tests/cases/compiler/genericFunctionInference1.ts new file mode 100644 index 0000000000000..f2a71ca7f0275 --- /dev/null +++ b/tests/cases/compiler/genericFunctionInference1.ts @@ -0,0 +1,187 @@ +// @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 }; +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 + +// #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), +);