Merge pull request #16072 from Microsoft/improveTypeArgumentInference
Infer from generic function return types
This commit is contained in:
commit
bcf84f4958
|
@ -7953,23 +7953,14 @@ namespace ts {
|
|||
return mapper;
|
||||
}
|
||||
|
||||
function getInferenceMapper(context: InferenceContext): TypeMapper {
|
||||
if (!context.mapper) {
|
||||
const mapper: TypeMapper = t => {
|
||||
const typeParameters = context.signature.typeParameters;
|
||||
for (let i = 0; i < typeParameters.length; i++) {
|
||||
if (t === typeParameters[i]) {
|
||||
context.inferences[i].isFixed = true;
|
||||
return getInferredType(context, i);
|
||||
}
|
||||
}
|
||||
return t;
|
||||
};
|
||||
mapper.mappedTypes = context.signature.typeParameters;
|
||||
mapper.context = context;
|
||||
context.mapper = mapper;
|
||||
}
|
||||
return context.mapper;
|
||||
function isInferenceContext(mapper: TypeMapper): mapper is InferenceContext {
|
||||
return !!(<InferenceContext>mapper).signature;
|
||||
}
|
||||
|
||||
function cloneTypeMapper(mapper: TypeMapper): TypeMapper {
|
||||
return mapper && isInferenceContext(mapper) ?
|
||||
createInferenceContext(mapper.signature, mapper.flags | InferenceFlags.NoDefault, mapper.inferences) :
|
||||
mapper;
|
||||
}
|
||||
|
||||
function identityMapper(type: Type): Type {
|
||||
|
@ -10165,23 +10156,45 @@ namespace ts {
|
|||
}
|
||||
}
|
||||
|
||||
function createInferenceContext(signature: Signature, inferUnionTypes: boolean, useAnyForNoInferences: boolean): InferenceContext {
|
||||
const inferences = map(signature.typeParameters, createTypeInferencesObject);
|
||||
function createInferenceContext(signature: Signature, flags: InferenceFlags, baseInferences?: InferenceInfo[]): InferenceContext {
|
||||
const inferences = baseInferences ? map(baseInferences, cloneInferenceInfo) : map(signature.typeParameters, createInferenceInfo);
|
||||
const context = mapper as InferenceContext;
|
||||
context.mappedTypes = signature.typeParameters;
|
||||
context.signature = signature;
|
||||
context.inferences = inferences;
|
||||
context.flags = flags;
|
||||
return context;
|
||||
|
||||
function mapper(t: Type): Type {
|
||||
for (let i = 0; i < inferences.length; i++) {
|
||||
if (t === inferences[i].typeParameter) {
|
||||
inferences[i].isFixed = true;
|
||||
return getInferredType(context, i);
|
||||
}
|
||||
}
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
function createInferenceInfo(typeParameter: TypeParameter): InferenceInfo {
|
||||
return {
|
||||
signature,
|
||||
inferUnionTypes,
|
||||
inferences,
|
||||
inferredTypes: new Array(signature.typeParameters.length),
|
||||
useAnyForNoInferences
|
||||
typeParameter,
|
||||
candidates: undefined,
|
||||
inferredType: undefined,
|
||||
priority: undefined,
|
||||
topLevel: true,
|
||||
isFixed: false
|
||||
};
|
||||
}
|
||||
|
||||
function createTypeInferencesObject(): TypeInferences {
|
||||
function cloneInferenceInfo(inference: InferenceInfo): InferenceInfo {
|
||||
return {
|
||||
primary: undefined,
|
||||
secondary: undefined,
|
||||
topLevel: true,
|
||||
isFixed: false,
|
||||
typeParameter: inference.typeParameter,
|
||||
candidates: inference.candidates && inference.candidates.slice(),
|
||||
inferredType: inference.inferredType,
|
||||
priority: inference.priority,
|
||||
topLevel: inference.topLevel,
|
||||
isFixed: inference.isFixed
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -10218,10 +10231,9 @@ namespace ts {
|
|||
if (properties.length === 0 && !indexInfo) {
|
||||
return undefined;
|
||||
}
|
||||
const typeVariable = <TypeVariable>getIndexedAccessType((<IndexType>getConstraintTypeFromMappedType(target)).type, getTypeParameterFromMappedType(target));
|
||||
const typeVariableArray = [typeVariable];
|
||||
const typeInferences = createTypeInferencesObject();
|
||||
const typeInferencesArray = [typeInferences];
|
||||
const typeParameter = <TypeParameter>getIndexedAccessType((<IndexType>getConstraintTypeFromMappedType(target)).type, getTypeParameterFromMappedType(target));
|
||||
const inference = createInferenceInfo(typeParameter);
|
||||
const inferences = [inference];
|
||||
const templateType = getTemplateTypeFromMappedType(target);
|
||||
const readonlyMask = target.declaration.readonlyToken ? false : true;
|
||||
const optionalMask = target.declaration.questionToken ? 0 : SymbolFlags.Optional;
|
||||
|
@ -10247,22 +10259,15 @@ namespace ts {
|
|||
return createAnonymousType(undefined, members, emptyArray, emptyArray, indexInfo, undefined);
|
||||
|
||||
function inferTargetType(sourceType: Type): Type {
|
||||
typeInferences.primary = undefined;
|
||||
typeInferences.secondary = undefined;
|
||||
inferTypes(typeVariableArray, typeInferencesArray, sourceType, templateType);
|
||||
const inferences = typeInferences.primary || typeInferences.secondary;
|
||||
return inferences && getUnionType(inferences, /*subtypeReduction*/ true);
|
||||
inference.candidates = undefined;
|
||||
inferTypes(inferences, sourceType, templateType);
|
||||
return inference.candidates && getUnionType(inference.candidates, /*subtypeReduction*/ true);
|
||||
}
|
||||
}
|
||||
|
||||
function inferTypesWithContext(context: InferenceContext, originalSource: Type, originalTarget: Type) {
|
||||
inferTypes(context.signature.typeParameters, context.inferences, originalSource, originalTarget);
|
||||
}
|
||||
|
||||
function inferTypes(typeVariables: TypeVariable[], typeInferences: TypeInferences[], originalSource: Type, originalTarget: Type) {
|
||||
function inferTypes(inferences: InferenceInfo[], originalSource: Type, originalTarget: Type, priority: InferencePriority = 0) {
|
||||
let symbolStack: Symbol[];
|
||||
let visited: Map<boolean>;
|
||||
let inferiority = 0;
|
||||
inferFromTypes(originalSource, originalTarget);
|
||||
|
||||
function inferFromTypes(source: Type, target: Type) {
|
||||
|
@ -10322,32 +10327,26 @@ namespace ts {
|
|||
// Because the anyFunctionType is internal, it should not be exposed to the user by adding
|
||||
// it as an inference candidate. Hopefully, a better candidate will come along that does
|
||||
// not contain anyFunctionType when we come back to this argument for its second round
|
||||
// of inference.
|
||||
if (source.flags & TypeFlags.ContainsAnyFunctionType) {
|
||||
// of inference. Also, we exclude inferences for silentNeverType which is used as a wildcard
|
||||
// when constructing types from type parameters that had no inference candidates.
|
||||
if (source.flags & TypeFlags.ContainsAnyFunctionType || source === silentNeverType) {
|
||||
return;
|
||||
}
|
||||
for (let i = 0; i < typeVariables.length; i++) {
|
||||
if (target === typeVariables[i]) {
|
||||
const inferences = typeInferences[i];
|
||||
if (!inferences.isFixed) {
|
||||
// Any inferences that are made to a type parameter in a union type are inferior
|
||||
// to inferences made to a flat (non-union) type. This is because if we infer to
|
||||
// T | string[], we really don't know if we should be inferring to T or not (because
|
||||
// the correct constituent on the target side could be string[]). Therefore, we put
|
||||
// such inferior inferences into a secondary bucket, and only use them if the primary
|
||||
// bucket is empty.
|
||||
const candidates = inferiority ?
|
||||
inferences.secondary || (inferences.secondary = []) :
|
||||
inferences.primary || (inferences.primary = []);
|
||||
if (!contains(candidates, source)) {
|
||||
candidates.push(source);
|
||||
}
|
||||
if (target.flags & TypeFlags.TypeParameter && !isTypeParameterAtTopLevel(originalTarget, <TypeParameter>target)) {
|
||||
inferences.topLevel = false;
|
||||
}
|
||||
const inference = getInferenceInfoForType(target);
|
||||
if (inference) {
|
||||
if (!inference.isFixed) {
|
||||
if (!inference.candidates || priority < inference.priority) {
|
||||
inference.candidates = [source];
|
||||
inference.priority = priority;
|
||||
}
|
||||
else if (priority === inference.priority) {
|
||||
inference.candidates.push(source);
|
||||
}
|
||||
if (!(priority & InferencePriority.ReturnType) && target.flags & TypeFlags.TypeParameter && !isTypeParameterAtTopLevel(originalTarget, <TypeParameter>target)) {
|
||||
inference.topLevel = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (getObjectFlags(source) & ObjectFlags.Reference && getObjectFlags(target) & ObjectFlags.Reference && (<TypeReference>source).target === (<TypeReference>target).target) {
|
||||
|
@ -10365,7 +10364,7 @@ namespace ts {
|
|||
let typeVariable: TypeVariable;
|
||||
// First infer to each type in union or intersection that isn't a type variable
|
||||
for (const t of targetTypes) {
|
||||
if (t.flags & TypeFlags.TypeVariable && contains(typeVariables, t)) {
|
||||
if (getInferenceInfoForType(t)) {
|
||||
typeVariable = <TypeVariable>t;
|
||||
typeVariableCount++;
|
||||
}
|
||||
|
@ -10377,9 +10376,10 @@ namespace ts {
|
|||
// variable. This gives meaningful results for union types in co-variant positions and intersection
|
||||
// types in contra-variant positions (such as callback parameters).
|
||||
if (typeVariableCount === 1) {
|
||||
inferiority++;
|
||||
const savePriority = priority;
|
||||
priority |= InferencePriority.NakedTypeVariable;
|
||||
inferFromTypes(source, typeVariable);
|
||||
inferiority--;
|
||||
priority = savePriority;
|
||||
}
|
||||
}
|
||||
else if (source.flags & TypeFlags.UnionOrIntersection) {
|
||||
|
@ -10419,6 +10419,17 @@ namespace ts {
|
|||
}
|
||||
}
|
||||
|
||||
function getInferenceInfoForType(type: Type) {
|
||||
if (type.flags & TypeFlags.TypeVariable) {
|
||||
for (const inference of inferences) {
|
||||
if (type === inference.typeParameter) {
|
||||
return inference;
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function inferFromObjectTypes(source: Type, target: Type) {
|
||||
if (getObjectFlags(target) & ObjectFlags.Mapped) {
|
||||
const constraintType = getConstraintTypeFromMappedType(<MappedType>target);
|
||||
|
@ -10427,13 +10438,14 @@ namespace ts {
|
|||
// where T is a type variable. Use inferTypeForHomomorphicMappedType to infer a suitable source
|
||||
// type and then make a secondary inference from that type to T. We make a secondary inference
|
||||
// such that direct inferences to T get priority over inferences to Partial<T>, for example.
|
||||
const index = indexOf(typeVariables, (<IndexType>constraintType).type);
|
||||
if (index >= 0 && !typeInferences[index].isFixed) {
|
||||
const inference = getInferenceInfoForType((<IndexType>constraintType).type);
|
||||
if (inference && !inference.isFixed) {
|
||||
const inferredType = inferTypeForHomomorphicMappedType(source, <MappedType>target);
|
||||
if (inferredType) {
|
||||
inferiority++;
|
||||
inferFromTypes(inferredType, typeVariables[index]);
|
||||
inferiority--;
|
||||
const savePriority = priority;
|
||||
priority |= InferencePriority.MappedType;
|
||||
inferFromTypes(inferredType, inference.typeParameter);
|
||||
priority = savePriority;
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
@ -10532,66 +10544,68 @@ namespace ts {
|
|||
return type.flags & TypeFlags.Union ? getUnionType(reducedTypes) : getIntersectionType(reducedTypes);
|
||||
}
|
||||
|
||||
function getInferenceCandidates(context: InferenceContext, index: number): Type[] {
|
||||
const inferences = context.inferences[index];
|
||||
return inferences.primary || inferences.secondary || emptyArray;
|
||||
}
|
||||
|
||||
function hasPrimitiveConstraint(type: TypeParameter): boolean {
|
||||
const constraint = getConstraintOfTypeParameter(type);
|
||||
return constraint && maybeTypeOfKind(constraint, TypeFlags.Primitive | TypeFlags.Index);
|
||||
}
|
||||
|
||||
function getInferredType(context: InferenceContext, index: number): Type {
|
||||
let inferredType = context.inferredTypes[index];
|
||||
const inference = context.inferences[index];
|
||||
let inferredType = inference.inferredType;
|
||||
let inferenceSucceeded: boolean;
|
||||
if (!inferredType) {
|
||||
const inferences = getInferenceCandidates(context, index);
|
||||
if (inferences.length) {
|
||||
if (inference.candidates) {
|
||||
// We widen inferred literal types if
|
||||
// all inferences were made to top-level ocurrences of the type parameter, and
|
||||
// the type parameter has no constraint or its constraint includes no primitive or literal types, and
|
||||
// the type parameter was fixed during inference or does not occur at top-level in the return type.
|
||||
const signature = context.signature;
|
||||
const widenLiteralTypes = context.inferences[index].topLevel &&
|
||||
!hasPrimitiveConstraint(signature.typeParameters[index]) &&
|
||||
(context.inferences[index].isFixed || !isTypeParameterAtTopLevel(getReturnTypeOfSignature(signature), signature.typeParameters[index]));
|
||||
const baseInferences = widenLiteralTypes ? sameMap(inferences, getWidenedLiteralType) : inferences;
|
||||
// Infer widened union or supertype, or the unknown type for no common supertype
|
||||
const unionOrSuperType = context.inferUnionTypes ? getUnionType(baseInferences, /*subtypeReduction*/ true) : getCommonSupertype(baseInferences);
|
||||
const widenLiteralTypes = inference.topLevel &&
|
||||
!hasPrimitiveConstraint(inference.typeParameter) &&
|
||||
(inference.isFixed || !isTypeParameterAtTopLevel(getReturnTypeOfSignature(signature), inference.typeParameter));
|
||||
const baseCandidates = widenLiteralTypes ? sameMap(inference.candidates, getWidenedLiteralType) : inference.candidates;
|
||||
// Infer widened union or supertype, or the unknown type for no common supertype. We infer union types
|
||||
// for inferences coming from return types in order to avoid common supertype failures.
|
||||
const unionOrSuperType = context.flags & InferenceFlags.InferUnionTypes || inference.priority & InferencePriority.ReturnType ?
|
||||
getUnionType(baseCandidates, /*subtypeReduction*/ true) : getCommonSupertype(baseCandidates);
|
||||
inferredType = unionOrSuperType ? getWidenedType(unionOrSuperType) : unknownType;
|
||||
inferenceSucceeded = !!unionOrSuperType;
|
||||
}
|
||||
else {
|
||||
// Infer either the default or the empty object type when no inferences were
|
||||
// made. It is important to remember that in this case, inference still
|
||||
// succeeds, meaning there is no error for not having inference candidates. An
|
||||
// inference error only occurs when there are *conflicting* candidates, i.e.
|
||||
// candidates with no common supertype.
|
||||
const defaultType = getDefaultFromTypeParameter(context.signature.typeParameters[index]);
|
||||
if (defaultType) {
|
||||
// Instantiate the default type. Any forward reference to a type
|
||||
// parameter should be instantiated to the empty object type.
|
||||
inferredType = instantiateType(defaultType,
|
||||
combineTypeMappers(
|
||||
createBackreferenceMapper(context.signature.typeParameters, index),
|
||||
getInferenceMapper(context)));
|
||||
if (context.flags & InferenceFlags.NoDefault) {
|
||||
// We use silentNeverType as the wildcard that signals no inferences.
|
||||
inferredType = silentNeverType;
|
||||
}
|
||||
else {
|
||||
inferredType = context.useAnyForNoInferences ? anyType : emptyObjectType;
|
||||
// Infer either the default or the empty object type when no inferences were
|
||||
// made. It is important to remember that in this case, inference still
|
||||
// succeeds, meaning there is no error for not having inference candidates. An
|
||||
// inference error only occurs when there are *conflicting* candidates, i.e.
|
||||
// candidates with no common supertype.
|
||||
const defaultType = getDefaultFromTypeParameter(inference.typeParameter);
|
||||
if (defaultType) {
|
||||
// Instantiate the default type. Any forward reference to a type
|
||||
// parameter should be instantiated to the empty object type.
|
||||
inferredType = instantiateType(defaultType,
|
||||
combineTypeMappers(
|
||||
createBackreferenceMapper(context.signature.typeParameters, index),
|
||||
context));
|
||||
}
|
||||
else {
|
||||
inferredType = context.flags & InferenceFlags.AnyDefault ? anyType : emptyObjectType;
|
||||
}
|
||||
}
|
||||
|
||||
inferenceSucceeded = true;
|
||||
}
|
||||
context.inferredTypes[index] = inferredType;
|
||||
inference.inferredType = inferredType;
|
||||
|
||||
// Only do the constraint check if inference succeeded (to prevent cascading errors)
|
||||
if (inferenceSucceeded) {
|
||||
const constraint = getConstraintOfTypeParameter(context.signature.typeParameters[index]);
|
||||
if (constraint) {
|
||||
const instantiatedConstraint = instantiateType(constraint, getInferenceMapper(context));
|
||||
const instantiatedConstraint = instantiateType(constraint, context);
|
||||
if (!isTypeAssignableTo(inferredType, getTypeWithThisArgument(instantiatedConstraint, inferredType))) {
|
||||
context.inferredTypes[index] = inferredType = instantiatedConstraint;
|
||||
inference.inferredType = inferredType = instantiatedConstraint;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10606,10 +10620,11 @@ namespace ts {
|
|||
}
|
||||
|
||||
function getInferredTypes(context: InferenceContext): Type[] {
|
||||
for (let i = 0; i < context.inferredTypes.length; i++) {
|
||||
getInferredType(context, i);
|
||||
const result: Type[] = [];
|
||||
for (let i = 0; i < context.inferences.length; i++) {
|
||||
result.push(getInferredType(context, i));
|
||||
}
|
||||
return context.inferredTypes;
|
||||
return result;
|
||||
}
|
||||
|
||||
// EXPRESSION TYPE CHECKING
|
||||
|
@ -14865,26 +14880,25 @@ 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): Signature {
|
||||
const context = createInferenceContext(signature, /*inferUnionTypes*/ true, /*useAnyForNoInferences*/ false);
|
||||
const context = createInferenceContext(signature, InferenceFlags.InferUnionTypes);
|
||||
forEachMatchingParameterType(contextualSignature, signature, (source, target) => {
|
||||
// Type parameters from outer context referenced by source type are fixed by instantiation of the source type
|
||||
inferTypesWithContext(context, instantiateType(source, contextualMapper), target);
|
||||
inferTypes(context.inferences, instantiateType(source, contextualMapper), target);
|
||||
});
|
||||
return getSignatureInstantiation(signature, getInferredTypes(context));
|
||||
}
|
||||
|
||||
function inferTypeArguments(node: CallLikeExpression, signature: Signature, args: Expression[], excludeArgument: boolean[], context: InferenceContext): void {
|
||||
const typeParameters = signature.typeParameters;
|
||||
const inferenceMapper = getInferenceMapper(context);
|
||||
function inferTypeArguments(node: CallLikeExpression, signature: Signature, args: Expression[], excludeArgument: boolean[], context: InferenceContext): Type[] {
|
||||
const inferences = context.inferences;
|
||||
|
||||
// Clear out all the inference results from the last time inferTypeArguments was called on this context
|
||||
for (let i = 0; i < typeParameters.length; i++) {
|
||||
for (let i = 0; i < inferences.length; i++) {
|
||||
// As an optimization, we don't have to clear (and later recompute) inferred types
|
||||
// for type parameters that have already been fixed on the previous call to inferTypeArguments.
|
||||
// It would be just as correct to reset all of them. But then we'd be repeating the same work
|
||||
// for the type parameters that were fixed, namely the work done by getInferredType.
|
||||
if (!context.inferences[i].isFixed) {
|
||||
context.inferredTypes[i] = undefined;
|
||||
if (!inferences[i].isFixed) {
|
||||
inferences[i].inferredType = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14899,11 +14913,29 @@ namespace ts {
|
|||
context.failedTypeParameterIndex = undefined;
|
||||
}
|
||||
|
||||
// If a contextual type is available, infer from that type to the return type of the call expression. For
|
||||
// example, given a 'function wrap<T, U>(cb: (x: T) => U): (x: T) => U' and a call expression
|
||||
// 'let f: (x: string) => number = wrap(s => s.length)', we infer from the declared type of 'f' to the
|
||||
// return type of 'wrap'.
|
||||
if (isExpression(node)) {
|
||||
const contextualType = getContextualType(node);
|
||||
if (contextualType) {
|
||||
// We clone the contextual mapper to avoid disturbing a resolution in progress for an
|
||||
// outer call expression. Effectively we just want a snapshot of whatever has been
|
||||
// inferred for any outer call expression so far.
|
||||
const mapper = cloneTypeMapper(getContextualMapper(node));
|
||||
const instantiatedType = instantiateType(contextualType, mapper);
|
||||
const returnType = getReturnTypeOfSignature(signature);
|
||||
// Inferences made from return types have lower priority than all other inferences.
|
||||
inferTypes(context.inferences, instantiatedType, returnType, InferencePriority.ReturnType);
|
||||
}
|
||||
}
|
||||
|
||||
const thisType = getThisTypeOfSignature(signature);
|
||||
if (thisType) {
|
||||
const thisArgumentNode = getThisArgumentOfCall(node);
|
||||
const thisArgumentType = thisArgumentNode ? checkExpression(thisArgumentNode) : voidType;
|
||||
inferTypesWithContext(context, thisArgumentType, thisType);
|
||||
inferTypes(context.inferences, thisArgumentType, thisType);
|
||||
}
|
||||
|
||||
// We perform two passes over the arguments. In the first pass we infer from all arguments, but use
|
||||
|
@ -14921,11 +14953,11 @@ namespace ts {
|
|||
if (argType === undefined) {
|
||||
// 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 : inferenceMapper;
|
||||
const mapper = excludeArgument && excludeArgument[i] !== undefined ? identityMapper : context;
|
||||
argType = checkExpressionWithContextualType(arg, paramType, mapper);
|
||||
}
|
||||
|
||||
inferTypesWithContext(context, argType, paramType);
|
||||
inferTypes(context.inferences, argType, paramType);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14940,12 +14972,11 @@ namespace ts {
|
|||
if (excludeArgument[i] === false) {
|
||||
const arg = args[i];
|
||||
const paramType = getTypeAtPosition(signature, i);
|
||||
inferTypesWithContext(context, checkExpressionWithContextualType(arg, paramType, inferenceMapper), paramType);
|
||||
inferTypes(context.inferences, checkExpressionWithContextualType(arg, paramType, context), paramType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getInferredTypes(context);
|
||||
return getInferredTypes(context);
|
||||
}
|
||||
|
||||
function checkTypeArguments(signature: Signature, typeArgumentNodes: TypeNode[], typeArgumentTypes: Type[], reportErrors: boolean, headMessage?: DiagnosticMessage): boolean {
|
||||
|
@ -15527,7 +15558,7 @@ namespace ts {
|
|||
else {
|
||||
Debug.assert(resultOfFailedInference.failedTypeParameterIndex >= 0);
|
||||
const failedTypeParameter = candidateForTypeArgumentError.typeParameters[resultOfFailedInference.failedTypeParameterIndex];
|
||||
const inferenceCandidates = getInferenceCandidates(resultOfFailedInference, resultOfFailedInference.failedTypeParameterIndex);
|
||||
const inferenceCandidates = resultOfFailedInference.inferences[resultOfFailedInference.failedTypeParameterIndex].candidates;
|
||||
|
||||
let diagnosticChainHead = chainDiagnosticMessages(/*details*/ undefined, // details will be provided by call to reportNoCommonSupertypeError
|
||||
Diagnostics.The_type_argument_for_type_parameter_0_cannot_be_inferred_from_the_usage_Consider_specifying_the_type_arguments_explicitly,
|
||||
|
@ -15600,7 +15631,7 @@ namespace ts {
|
|||
let candidate: Signature;
|
||||
let typeArgumentsAreValid: boolean;
|
||||
const inferenceContext = originalCandidate.typeParameters
|
||||
? createInferenceContext(originalCandidate, /*inferUnionTypes*/ false, /*useAnyForNoInferences*/ isInJavaScriptFile(node))
|
||||
? createInferenceContext(originalCandidate, /*flags*/ isInJavaScriptFile(node) ? InferenceFlags.AnyDefault : 0)
|
||||
: undefined;
|
||||
|
||||
while (true) {
|
||||
|
@ -15612,8 +15643,7 @@ namespace ts {
|
|||
typeArgumentsAreValid = checkTypeArguments(candidate, typeArguments, typeArgumentTypes, /*reportErrors*/ false);
|
||||
}
|
||||
else {
|
||||
inferTypeArguments(node, candidate, args, excludeArgument, inferenceContext);
|
||||
typeArgumentTypes = inferenceContext.inferredTypes;
|
||||
typeArgumentTypes = inferTypeArguments(node, candidate, args, excludeArgument, inferenceContext);
|
||||
typeArgumentsAreValid = inferenceContext.failedTypeParameterIndex === undefined;
|
||||
}
|
||||
if (!typeArgumentsAreValid) {
|
||||
|
@ -16187,7 +16217,7 @@ namespace ts {
|
|||
for (let i = 0; i < len; i++) {
|
||||
const declaration = <ParameterDeclaration>signature.parameters[i].valueDeclaration;
|
||||
if (declaration.type) {
|
||||
inferTypesWithContext(mapper.context, getTypeFromTypeNode(declaration.type), getTypeAtPosition(context, i));
|
||||
inferTypes((<InferenceContext>mapper).inferences, getTypeFromTypeNode(declaration.type), getTypeAtPosition(context, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16273,7 +16303,7 @@ namespace ts {
|
|||
// T in the second overload so that we do not infer Base as a candidate for T
|
||||
// (inferring Base would make type argument inference inconsistent between the two
|
||||
// overloads).
|
||||
inferTypesWithContext(mapper.context, links.type, instantiateType(contextualType, mapper));
|
||||
inferTypes((<InferenceContext>mapper).inferences, links.type, instantiateType(contextualType, mapper));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3343,30 +3343,36 @@ namespace ts {
|
|||
(t: TypeParameter): Type;
|
||||
mappedTypes?: Type[]; // Types mapped by this mapper
|
||||
instantiations?: Type[]; // Cache of instantiations created using this type mapper.
|
||||
context?: InferenceContext; // The inference context this mapper was created from.
|
||||
// Only inference mappers have this set (in createInferenceMapper).
|
||||
// The identity mapper and regular instantiation mappers do not need it.
|
||||
}
|
||||
|
||||
export const enum InferencePriority {
|
||||
NakedTypeVariable = 1 << 0, // Naked type variable in union or intersection type
|
||||
MappedType = 1 << 1, // Reverse inference for mapped type
|
||||
ReturnType = 1 << 2, // Inference made from return type of generic function
|
||||
}
|
||||
|
||||
export interface InferenceInfo {
|
||||
typeParameter: TypeParameter;
|
||||
candidates: Type[];
|
||||
inferredType: Type;
|
||||
priority: InferencePriority;
|
||||
topLevel: boolean;
|
||||
isFixed: boolean;
|
||||
}
|
||||
|
||||
export const enum InferenceFlags {
|
||||
InferUnionTypes = 1 << 0, // Infer union types for disjoint candidates (otherwise unknownType)
|
||||
NoDefault = 1 << 1, // Infer unknownType for no inferences (otherwise anyType or emptyObjectType)
|
||||
AnyDefault = 1 << 2, // Infer anyType for no inferences (otherwise emptyObjectType)
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export interface TypeInferences {
|
||||
primary: Type[]; // Inferences made directly to a type parameter
|
||||
secondary: Type[]; // Inferences made to a type parameter in a union type
|
||||
topLevel: boolean; // True if all inferences were made from top-level (not nested in object type) locations
|
||||
isFixed: boolean; // Whether the type parameter is fixed, as defined in section 4.12.2 of the TypeScript spec
|
||||
// If a type parameter is fixed, no more inferences can be made for the type parameter
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export interface InferenceContext {
|
||||
export interface InferenceContext extends TypeMapper {
|
||||
signature: Signature; // Generic signature for which inferences are made
|
||||
inferUnionTypes: boolean; // Infer union types for disjoint candidates (otherwise undefinedType)
|
||||
inferences: TypeInferences[]; // Inferences made for each type parameter
|
||||
inferredTypes: Type[]; // Inferred type for each type parameter
|
||||
mapper?: TypeMapper; // Type mapper for this inference context
|
||||
inferences: InferenceInfo[]; // Inferences made for each type parameter
|
||||
flags: InferenceFlags; // Inference flags
|
||||
failedTypeParameterIndex?: number; // Index of type parameter for which inference failed
|
||||
// It is optional because in contextual signature instantiation, nothing fails
|
||||
useAnyForNoInferences?: boolean; // Use any instead of {} for no inferences
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
|
|
|
@ -26,7 +26,7 @@ var c3 = new C<number>();
|
|||
var c4: C<any> = new C();
|
||||
>c4 : C<any>
|
||||
>C : C<T>
|
||||
>new C() : C<{}>
|
||||
>new C() : C<any>
|
||||
>C : typeof C
|
||||
|
||||
class D<T> {
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
tests/cases/compiler/inferFromGenericFunctionReturnTypes1.ts(68,16): error TS2339: Property 'toUpperCase' does not exist on type 'number'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/inferFromGenericFunctionReturnTypes1.ts (1 errors) ====
|
||||
// Repro from #15680
|
||||
|
||||
// This is a contrived class. We could do the same thing with Observables, etc.
|
||||
class SetOf<A> {
|
||||
_store: A[];
|
||||
|
||||
add(a: A) {
|
||||
this._store.push(a);
|
||||
}
|
||||
|
||||
transform<B>(transformer: (a: SetOf<A>) => SetOf<B>): SetOf<B> {
|
||||
return transformer(this);
|
||||
}
|
||||
|
||||
forEach(fn: (a: A, index: number) => void) {
|
||||
this._store.forEach((a, i) => fn(a, i));
|
||||
}
|
||||
}
|
||||
|
||||
function compose<A, B, C, D, E>(
|
||||
fnA: (a: SetOf<A>) => SetOf<B>,
|
||||
fnB: (b: SetOf<B>) => SetOf<C>,
|
||||
fnC: (c: SetOf<C>) => SetOf<D>,
|
||||
fnD: (c: SetOf<D>) => SetOf<E>,
|
||||
):(x: SetOf<A>) => SetOf<E>;
|
||||
/* ... etc ... */
|
||||
function compose<T>(...fns: ((x: T) => T)[]): (x: T) => T {
|
||||
return (x: T) => fns.reduce((prev, fn) => fn(prev), x);
|
||||
}
|
||||
|
||||
function map<A, B>(fn: (a: A) => B): (s: SetOf<A>) => SetOf<B> {
|
||||
return (a: SetOf<A>) => {
|
||||
const b: SetOf<B> = new SetOf();
|
||||
a.forEach(x => b.add(fn(x)));
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
function filter<A>(predicate: (a: A) => boolean): (s: SetOf<A>) => SetOf<A> {
|
||||
return (a: SetOf<A>) => {
|
||||
const result = new SetOf<A>();
|
||||
a.forEach(x => {
|
||||
if (predicate(x)) result.add(x);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
const testSet = new SetOf<number>();
|
||||
testSet.add(1);
|
||||
testSet.add(2);
|
||||
testSet.add(3);
|
||||
|
||||
testSet.transform(
|
||||
compose(
|
||||
filter(x => x % 1 === 0),
|
||||
map(x => x + x),
|
||||
map(x => x + '!!!'),
|
||||
map(x => x.toUpperCase())
|
||||
)
|
||||
)
|
||||
|
||||
testSet.transform(
|
||||
compose(
|
||||
filter(x => x % 1 === 0),
|
||||
map(x => x + x),
|
||||
map(x => 123), // Whoops a bug
|
||||
map(x => x.toUpperCase()) // causes an error!
|
||||
~~~~~~~~~~~
|
||||
!!! error TS2339: Property 'toUpperCase' does not exist on type 'number'.
|
||||
)
|
||||
)
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
//// [inferFromGenericFunctionReturnTypes1.ts]
|
||||
// Repro from #15680
|
||||
|
||||
// This is a contrived class. We could do the same thing with Observables, etc.
|
||||
class SetOf<A> {
|
||||
_store: A[];
|
||||
|
||||
add(a: A) {
|
||||
this._store.push(a);
|
||||
}
|
||||
|
||||
transform<B>(transformer: (a: SetOf<A>) => SetOf<B>): SetOf<B> {
|
||||
return transformer(this);
|
||||
}
|
||||
|
||||
forEach(fn: (a: A, index: number) => void) {
|
||||
this._store.forEach((a, i) => fn(a, i));
|
||||
}
|
||||
}
|
||||
|
||||
function compose<A, B, C, D, E>(
|
||||
fnA: (a: SetOf<A>) => SetOf<B>,
|
||||
fnB: (b: SetOf<B>) => SetOf<C>,
|
||||
fnC: (c: SetOf<C>) => SetOf<D>,
|
||||
fnD: (c: SetOf<D>) => SetOf<E>,
|
||||
):(x: SetOf<A>) => SetOf<E>;
|
||||
/* ... etc ... */
|
||||
function compose<T>(...fns: ((x: T) => T)[]): (x: T) => T {
|
||||
return (x: T) => fns.reduce((prev, fn) => fn(prev), x);
|
||||
}
|
||||
|
||||
function map<A, B>(fn: (a: A) => B): (s: SetOf<A>) => SetOf<B> {
|
||||
return (a: SetOf<A>) => {
|
||||
const b: SetOf<B> = new SetOf();
|
||||
a.forEach(x => b.add(fn(x)));
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
function filter<A>(predicate: (a: A) => boolean): (s: SetOf<A>) => SetOf<A> {
|
||||
return (a: SetOf<A>) => {
|
||||
const result = new SetOf<A>();
|
||||
a.forEach(x => {
|
||||
if (predicate(x)) result.add(x);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
const testSet = new SetOf<number>();
|
||||
testSet.add(1);
|
||||
testSet.add(2);
|
||||
testSet.add(3);
|
||||
|
||||
testSet.transform(
|
||||
compose(
|
||||
filter(x => x % 1 === 0),
|
||||
map(x => x + x),
|
||||
map(x => x + '!!!'),
|
||||
map(x => x.toUpperCase())
|
||||
)
|
||||
)
|
||||
|
||||
testSet.transform(
|
||||
compose(
|
||||
filter(x => x % 1 === 0),
|
||||
map(x => x + x),
|
||||
map(x => 123), // Whoops a bug
|
||||
map(x => x.toUpperCase()) // causes an error!
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
//// [inferFromGenericFunctionReturnTypes1.js]
|
||||
// Repro from #15680
|
||||
// This is a contrived class. We could do the same thing with Observables, etc.
|
||||
var SetOf = (function () {
|
||||
function SetOf() {
|
||||
}
|
||||
SetOf.prototype.add = function (a) {
|
||||
this._store.push(a);
|
||||
};
|
||||
SetOf.prototype.transform = function (transformer) {
|
||||
return transformer(this);
|
||||
};
|
||||
SetOf.prototype.forEach = function (fn) {
|
||||
this._store.forEach(function (a, i) { return fn(a, i); });
|
||||
};
|
||||
return SetOf;
|
||||
}());
|
||||
/* ... etc ... */
|
||||
function compose() {
|
||||
var fns = [];
|
||||
for (var _i = 0; _i < arguments.length; _i++) {
|
||||
fns[_i] = arguments[_i];
|
||||
}
|
||||
return function (x) { return fns.reduce(function (prev, fn) { return fn(prev); }, x); };
|
||||
}
|
||||
function map(fn) {
|
||||
return function (a) {
|
||||
var b = new SetOf();
|
||||
a.forEach(function (x) { return b.add(fn(x)); });
|
||||
return b;
|
||||
};
|
||||
}
|
||||
function filter(predicate) {
|
||||
return function (a) {
|
||||
var result = new SetOf();
|
||||
a.forEach(function (x) {
|
||||
if (predicate(x))
|
||||
result.add(x);
|
||||
});
|
||||
return result;
|
||||
};
|
||||
}
|
||||
var testSet = new SetOf();
|
||||
testSet.add(1);
|
||||
testSet.add(2);
|
||||
testSet.add(3);
|
||||
testSet.transform(compose(filter(function (x) { return x % 1 === 0; }), map(function (x) { return x + x; }), map(function (x) { return x + '!!!'; }), map(function (x) { return x.toUpperCase(); })));
|
||||
testSet.transform(compose(filter(function (x) { return x % 1 === 0; }), map(function (x) { return x + x; }), map(function (x) { return 123; }), // Whoops a bug
|
||||
map(function (x) { return x.toUpperCase(); }) // causes an error!
|
||||
));
|
|
@ -0,0 +1,155 @@
|
|||
//// [inferFromGenericFunctionReturnTypes2.ts]
|
||||
type Mapper<T, U> = (x: T) => U;
|
||||
|
||||
declare function wrap<T, U>(cb: Mapper<T, U>): Mapper<T, U>;
|
||||
|
||||
declare function arrayize<T, U>(cb: Mapper<T, U>): Mapper<T, U[]>;
|
||||
|
||||
declare function combine<A, B, C>(f: (x: A) => B, g: (x: B) => C): (x: A) => C;
|
||||
|
||||
declare function foo(f: Mapper<string, number>): void;
|
||||
|
||||
let f1: Mapper<string, number> = s => s.length;
|
||||
let f2: Mapper<string, number> = wrap(s => s.length);
|
||||
let f3: Mapper<string, number[]> = arrayize(wrap(s => s.length));
|
||||
let f4: Mapper<string, boolean> = combine(wrap(s => s.length), wrap(n => n >= 10));
|
||||
|
||||
foo(wrap(s => s.length));
|
||||
|
||||
let a1 = ["a", "b"].map(s => s.length);
|
||||
let a2 = ["a", "b"].map(wrap(s => s.length));
|
||||
let a3 = ["a", "b"].map(wrap(arrayize(s => s.length)));
|
||||
let a4 = ["a", "b"].map(combine(wrap(s => s.length), wrap(n => n > 10)));
|
||||
let a5 = ["a", "b"].map(combine(identity, wrap(s => s.length)));
|
||||
let a6 = ["a", "b"].map(combine(wrap(s => s.length), identity));
|
||||
|
||||
// This is a contrived class. We could do the same thing with Observables, etc.
|
||||
class SetOf<A> {
|
||||
_store: A[];
|
||||
|
||||
add(a: A) {
|
||||
this._store.push(a);
|
||||
}
|
||||
|
||||
transform<B>(transformer: (a: SetOf<A>) => SetOf<B>): SetOf<B> {
|
||||
return transformer(this);
|
||||
}
|
||||
|
||||
forEach(fn: (a: A, index: number) => void) {
|
||||
this._store.forEach((a, i) => fn(a, i));
|
||||
}
|
||||
}
|
||||
|
||||
function compose<A, B, C, D, E>(
|
||||
fnA: (a: SetOf<A>) => SetOf<B>,
|
||||
fnB: (b: SetOf<B>) => SetOf<C>,
|
||||
fnC: (c: SetOf<C>) => SetOf<D>,
|
||||
fnD: (c: SetOf<D>) => SetOf<E>,
|
||||
):(x: SetOf<A>) => SetOf<E>;
|
||||
/* ... etc ... */
|
||||
function compose<T>(...fns: ((x: T) => T)[]): (x: T) => T {
|
||||
return (x: T) => fns.reduce((prev, fn) => fn(prev), x);
|
||||
}
|
||||
|
||||
function map<A, B>(fn: (a: A) => B): (s: SetOf<A>) => SetOf<B> {
|
||||
return (a: SetOf<A>) => {
|
||||
const b: SetOf<B> = new SetOf();
|
||||
a.forEach(x => b.add(fn(x)));
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
function filter<A>(predicate: (a: A) => boolean): (s: SetOf<A>) => SetOf<A> {
|
||||
return (a: SetOf<A>) => {
|
||||
const result = new SetOf<A>();
|
||||
a.forEach(x => {
|
||||
if (predicate(x)) result.add(x);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
const testSet = new SetOf<number>();
|
||||
testSet.add(1);
|
||||
testSet.add(2);
|
||||
testSet.add(3);
|
||||
|
||||
const t1 = testSet.transform(
|
||||
compose(
|
||||
filter(x => x % 1 === 0),
|
||||
map(x => x + x),
|
||||
map(x => x + '!!!'),
|
||||
map(x => x.toUpperCase())
|
||||
)
|
||||
)
|
||||
|
||||
declare function identity<T>(x: T): T;
|
||||
|
||||
const t2 = testSet.transform(
|
||||
compose(
|
||||
filter(x => x % 1 === 0),
|
||||
identity,
|
||||
map(x => x + '!!!'),
|
||||
map(x => x.toUpperCase())
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
//// [inferFromGenericFunctionReturnTypes2.js]
|
||||
var f1 = function (s) { return s.length; };
|
||||
var f2 = wrap(function (s) { return s.length; });
|
||||
var f3 = arrayize(wrap(function (s) { return s.length; }));
|
||||
var f4 = combine(wrap(function (s) { return s.length; }), wrap(function (n) { return n >= 10; }));
|
||||
foo(wrap(function (s) { return s.length; }));
|
||||
var a1 = ["a", "b"].map(function (s) { return s.length; });
|
||||
var a2 = ["a", "b"].map(wrap(function (s) { return s.length; }));
|
||||
var a3 = ["a", "b"].map(wrap(arrayize(function (s) { return s.length; })));
|
||||
var a4 = ["a", "b"].map(combine(wrap(function (s) { return s.length; }), wrap(function (n) { return n > 10; })));
|
||||
var a5 = ["a", "b"].map(combine(identity, wrap(function (s) { return s.length; })));
|
||||
var a6 = ["a", "b"].map(combine(wrap(function (s) { return s.length; }), identity));
|
||||
// This is a contrived class. We could do the same thing with Observables, etc.
|
||||
var SetOf = (function () {
|
||||
function SetOf() {
|
||||
}
|
||||
SetOf.prototype.add = function (a) {
|
||||
this._store.push(a);
|
||||
};
|
||||
SetOf.prototype.transform = function (transformer) {
|
||||
return transformer(this);
|
||||
};
|
||||
SetOf.prototype.forEach = function (fn) {
|
||||
this._store.forEach(function (a, i) { return fn(a, i); });
|
||||
};
|
||||
return SetOf;
|
||||
}());
|
||||
/* ... etc ... */
|
||||
function compose() {
|
||||
var fns = [];
|
||||
for (var _i = 0; _i < arguments.length; _i++) {
|
||||
fns[_i] = arguments[_i];
|
||||
}
|
||||
return function (x) { return fns.reduce(function (prev, fn) { return fn(prev); }, x); };
|
||||
}
|
||||
function map(fn) {
|
||||
return function (a) {
|
||||
var b = new SetOf();
|
||||
a.forEach(function (x) { return b.add(fn(x)); });
|
||||
return b;
|
||||
};
|
||||
}
|
||||
function filter(predicate) {
|
||||
return function (a) {
|
||||
var result = new SetOf();
|
||||
a.forEach(function (x) {
|
||||
if (predicate(x))
|
||||
result.add(x);
|
||||
});
|
||||
return result;
|
||||
};
|
||||
}
|
||||
var testSet = new SetOf();
|
||||
testSet.add(1);
|
||||
testSet.add(2);
|
||||
testSet.add(3);
|
||||
var t1 = testSet.transform(compose(filter(function (x) { return x % 1 === 0; }), map(function (x) { return x + x; }), map(function (x) { return x + '!!!'; }), map(function (x) { return x.toUpperCase(); })));
|
||||
var t2 = testSet.transform(compose(filter(function (x) { return x % 1 === 0; }), identity, map(function (x) { return x + '!!!'; }), map(function (x) { return x.toUpperCase(); })));
|
|
@ -0,0 +1,480 @@
|
|||
=== tests/cases/compiler/inferFromGenericFunctionReturnTypes2.ts ===
|
||||
type Mapper<T, U> = (x: T) => U;
|
||||
>Mapper : Symbol(Mapper, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 12))
|
||||
>U : Symbol(U, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 14))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 21))
|
||||
>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 12))
|
||||
>U : Symbol(U, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 14))
|
||||
|
||||
declare function wrap<T, U>(cb: Mapper<T, U>): Mapper<T, U>;
|
||||
>wrap : Symbol(wrap, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 32))
|
||||
>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 2, 22))
|
||||
>U : Symbol(U, Decl(inferFromGenericFunctionReturnTypes2.ts, 2, 24))
|
||||
>cb : Symbol(cb, Decl(inferFromGenericFunctionReturnTypes2.ts, 2, 28))
|
||||
>Mapper : Symbol(Mapper, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 2, 22))
|
||||
>U : Symbol(U, Decl(inferFromGenericFunctionReturnTypes2.ts, 2, 24))
|
||||
>Mapper : Symbol(Mapper, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 2, 22))
|
||||
>U : Symbol(U, Decl(inferFromGenericFunctionReturnTypes2.ts, 2, 24))
|
||||
|
||||
declare function arrayize<T, U>(cb: Mapper<T, U>): Mapper<T, U[]>;
|
||||
>arrayize : Symbol(arrayize, Decl(inferFromGenericFunctionReturnTypes2.ts, 2, 60))
|
||||
>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 4, 26))
|
||||
>U : Symbol(U, Decl(inferFromGenericFunctionReturnTypes2.ts, 4, 28))
|
||||
>cb : Symbol(cb, Decl(inferFromGenericFunctionReturnTypes2.ts, 4, 32))
|
||||
>Mapper : Symbol(Mapper, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 4, 26))
|
||||
>U : Symbol(U, Decl(inferFromGenericFunctionReturnTypes2.ts, 4, 28))
|
||||
>Mapper : Symbol(Mapper, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 4, 26))
|
||||
>U : Symbol(U, Decl(inferFromGenericFunctionReturnTypes2.ts, 4, 28))
|
||||
|
||||
declare function combine<A, B, C>(f: (x: A) => B, g: (x: B) => C): (x: A) => C;
|
||||
>combine : Symbol(combine, Decl(inferFromGenericFunctionReturnTypes2.ts, 4, 66))
|
||||
>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 25))
|
||||
>B : Symbol(B, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 27))
|
||||
>C : Symbol(C, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 30))
|
||||
>f : Symbol(f, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 34))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 38))
|
||||
>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 25))
|
||||
>B : Symbol(B, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 27))
|
||||
>g : Symbol(g, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 49))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 54))
|
||||
>B : Symbol(B, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 27))
|
||||
>C : Symbol(C, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 30))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 68))
|
||||
>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 25))
|
||||
>C : Symbol(C, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 30))
|
||||
|
||||
declare function foo(f: Mapper<string, number>): void;
|
||||
>foo : Symbol(foo, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 79))
|
||||
>f : Symbol(f, Decl(inferFromGenericFunctionReturnTypes2.ts, 8, 21))
|
||||
>Mapper : Symbol(Mapper, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 0))
|
||||
|
||||
let f1: Mapper<string, number> = s => s.length;
|
||||
>f1 : Symbol(f1, Decl(inferFromGenericFunctionReturnTypes2.ts, 10, 3))
|
||||
>Mapper : Symbol(Mapper, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 0))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 10, 32))
|
||||
>s.length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 10, 32))
|
||||
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
|
||||
let f2: Mapper<string, number> = wrap(s => s.length);
|
||||
>f2 : Symbol(f2, Decl(inferFromGenericFunctionReturnTypes2.ts, 11, 3))
|
||||
>Mapper : Symbol(Mapper, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 0))
|
||||
>wrap : Symbol(wrap, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 32))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 11, 38))
|
||||
>s.length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 11, 38))
|
||||
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
|
||||
let f3: Mapper<string, number[]> = arrayize(wrap(s => s.length));
|
||||
>f3 : Symbol(f3, Decl(inferFromGenericFunctionReturnTypes2.ts, 12, 3))
|
||||
>Mapper : Symbol(Mapper, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 0))
|
||||
>arrayize : Symbol(arrayize, Decl(inferFromGenericFunctionReturnTypes2.ts, 2, 60))
|
||||
>wrap : Symbol(wrap, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 32))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 12, 49))
|
||||
>s.length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 12, 49))
|
||||
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
|
||||
let f4: Mapper<string, boolean> = combine(wrap(s => s.length), wrap(n => n >= 10));
|
||||
>f4 : Symbol(f4, Decl(inferFromGenericFunctionReturnTypes2.ts, 13, 3))
|
||||
>Mapper : Symbol(Mapper, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 0))
|
||||
>combine : Symbol(combine, Decl(inferFromGenericFunctionReturnTypes2.ts, 4, 66))
|
||||
>wrap : Symbol(wrap, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 32))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 13, 47))
|
||||
>s.length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 13, 47))
|
||||
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
>wrap : Symbol(wrap, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 32))
|
||||
>n : Symbol(n, Decl(inferFromGenericFunctionReturnTypes2.ts, 13, 68))
|
||||
>n : Symbol(n, Decl(inferFromGenericFunctionReturnTypes2.ts, 13, 68))
|
||||
|
||||
foo(wrap(s => s.length));
|
||||
>foo : Symbol(foo, Decl(inferFromGenericFunctionReturnTypes2.ts, 6, 79))
|
||||
>wrap : Symbol(wrap, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 32))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 15, 9))
|
||||
>s.length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 15, 9))
|
||||
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
|
||||
let a1 = ["a", "b"].map(s => s.length);
|
||||
>a1 : Symbol(a1, Decl(inferFromGenericFunctionReturnTypes2.ts, 17, 3))
|
||||
>["a", "b"].map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 17, 24))
|
||||
>s.length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 17, 24))
|
||||
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
|
||||
let a2 = ["a", "b"].map(wrap(s => s.length));
|
||||
>a2 : Symbol(a2, Decl(inferFromGenericFunctionReturnTypes2.ts, 18, 3))
|
||||
>["a", "b"].map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>wrap : Symbol(wrap, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 32))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 18, 29))
|
||||
>s.length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 18, 29))
|
||||
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
|
||||
let a3 = ["a", "b"].map(wrap(arrayize(s => s.length)));
|
||||
>a3 : Symbol(a3, Decl(inferFromGenericFunctionReturnTypes2.ts, 19, 3))
|
||||
>["a", "b"].map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>wrap : Symbol(wrap, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 32))
|
||||
>arrayize : Symbol(arrayize, Decl(inferFromGenericFunctionReturnTypes2.ts, 2, 60))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 19, 38))
|
||||
>s.length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 19, 38))
|
||||
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
|
||||
let a4 = ["a", "b"].map(combine(wrap(s => s.length), wrap(n => n > 10)));
|
||||
>a4 : Symbol(a4, Decl(inferFromGenericFunctionReturnTypes2.ts, 20, 3))
|
||||
>["a", "b"].map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>combine : Symbol(combine, Decl(inferFromGenericFunctionReturnTypes2.ts, 4, 66))
|
||||
>wrap : Symbol(wrap, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 32))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 20, 37))
|
||||
>s.length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 20, 37))
|
||||
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
>wrap : Symbol(wrap, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 32))
|
||||
>n : Symbol(n, Decl(inferFromGenericFunctionReturnTypes2.ts, 20, 58))
|
||||
>n : Symbol(n, Decl(inferFromGenericFunctionReturnTypes2.ts, 20, 58))
|
||||
|
||||
let a5 = ["a", "b"].map(combine(identity, wrap(s => s.length)));
|
||||
>a5 : Symbol(a5, Decl(inferFromGenericFunctionReturnTypes2.ts, 21, 3))
|
||||
>["a", "b"].map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>combine : Symbol(combine, Decl(inferFromGenericFunctionReturnTypes2.ts, 4, 66))
|
||||
>identity : Symbol(identity, Decl(inferFromGenericFunctionReturnTypes2.ts, 82, 1))
|
||||
>wrap : Symbol(wrap, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 32))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 21, 47))
|
||||
>s.length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 21, 47))
|
||||
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
|
||||
let a6 = ["a", "b"].map(combine(wrap(s => s.length), identity));
|
||||
>a6 : Symbol(a6, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 3))
|
||||
>["a", "b"].map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>combine : Symbol(combine, Decl(inferFromGenericFunctionReturnTypes2.ts, 4, 66))
|
||||
>wrap : Symbol(wrap, Decl(inferFromGenericFunctionReturnTypes2.ts, 0, 32))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 37))
|
||||
>s.length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 37))
|
||||
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
>identity : Symbol(identity, Decl(inferFromGenericFunctionReturnTypes2.ts, 82, 1))
|
||||
|
||||
// This is a contrived class. We could do the same thing with Observables, etc.
|
||||
class SetOf<A> {
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 25, 12))
|
||||
|
||||
_store: A[];
|
||||
>_store : Symbol(SetOf._store, Decl(inferFromGenericFunctionReturnTypes2.ts, 25, 16))
|
||||
>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 25, 12))
|
||||
|
||||
add(a: A) {
|
||||
>add : Symbol(SetOf.add, Decl(inferFromGenericFunctionReturnTypes2.ts, 26, 14))
|
||||
>a : Symbol(a, Decl(inferFromGenericFunctionReturnTypes2.ts, 28, 6))
|
||||
>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 25, 12))
|
||||
|
||||
this._store.push(a);
|
||||
>this._store.push : Symbol(Array.push, Decl(lib.d.ts, --, --))
|
||||
>this._store : Symbol(SetOf._store, Decl(inferFromGenericFunctionReturnTypes2.ts, 25, 16))
|
||||
>this : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>_store : Symbol(SetOf._store, Decl(inferFromGenericFunctionReturnTypes2.ts, 25, 16))
|
||||
>push : Symbol(Array.push, Decl(lib.d.ts, --, --))
|
||||
>a : Symbol(a, Decl(inferFromGenericFunctionReturnTypes2.ts, 28, 6))
|
||||
}
|
||||
|
||||
transform<B>(transformer: (a: SetOf<A>) => SetOf<B>): SetOf<B> {
|
||||
>transform : Symbol(SetOf.transform, Decl(inferFromGenericFunctionReturnTypes2.ts, 30, 3))
|
||||
>B : Symbol(B, Decl(inferFromGenericFunctionReturnTypes2.ts, 32, 12))
|
||||
>transformer : Symbol(transformer, Decl(inferFromGenericFunctionReturnTypes2.ts, 32, 15))
|
||||
>a : Symbol(a, Decl(inferFromGenericFunctionReturnTypes2.ts, 32, 29))
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 25, 12))
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>B : Symbol(B, Decl(inferFromGenericFunctionReturnTypes2.ts, 32, 12))
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>B : Symbol(B, Decl(inferFromGenericFunctionReturnTypes2.ts, 32, 12))
|
||||
|
||||
return transformer(this);
|
||||
>transformer : Symbol(transformer, Decl(inferFromGenericFunctionReturnTypes2.ts, 32, 15))
|
||||
>this : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
}
|
||||
|
||||
forEach(fn: (a: A, index: number) => void) {
|
||||
>forEach : Symbol(SetOf.forEach, Decl(inferFromGenericFunctionReturnTypes2.ts, 34, 3))
|
||||
>fn : Symbol(fn, Decl(inferFromGenericFunctionReturnTypes2.ts, 36, 10))
|
||||
>a : Symbol(a, Decl(inferFromGenericFunctionReturnTypes2.ts, 36, 15))
|
||||
>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 25, 12))
|
||||
>index : Symbol(index, Decl(inferFromGenericFunctionReturnTypes2.ts, 36, 20))
|
||||
|
||||
this._store.forEach((a, i) => fn(a, i));
|
||||
>this._store.forEach : Symbol(Array.forEach, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>this._store : Symbol(SetOf._store, Decl(inferFromGenericFunctionReturnTypes2.ts, 25, 16))
|
||||
>this : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>_store : Symbol(SetOf._store, Decl(inferFromGenericFunctionReturnTypes2.ts, 25, 16))
|
||||
>forEach : Symbol(Array.forEach, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>a : Symbol(a, Decl(inferFromGenericFunctionReturnTypes2.ts, 37, 27))
|
||||
>i : Symbol(i, Decl(inferFromGenericFunctionReturnTypes2.ts, 37, 29))
|
||||
>fn : Symbol(fn, Decl(inferFromGenericFunctionReturnTypes2.ts, 36, 10))
|
||||
>a : Symbol(a, Decl(inferFromGenericFunctionReturnTypes2.ts, 37, 27))
|
||||
>i : Symbol(i, Decl(inferFromGenericFunctionReturnTypes2.ts, 37, 29))
|
||||
}
|
||||
}
|
||||
|
||||
function compose<A, B, C, D, E>(
|
||||
>compose : Symbol(compose, Decl(inferFromGenericFunctionReturnTypes2.ts, 39, 1), Decl(inferFromGenericFunctionReturnTypes2.ts, 46, 28))
|
||||
>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 17))
|
||||
>B : Symbol(B, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 19))
|
||||
>C : Symbol(C, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 22))
|
||||
>D : Symbol(D, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 25))
|
||||
>E : Symbol(E, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 28))
|
||||
|
||||
fnA: (a: SetOf<A>) => SetOf<B>,
|
||||
>fnA : Symbol(fnA, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 32))
|
||||
>a : Symbol(a, Decl(inferFromGenericFunctionReturnTypes2.ts, 42, 8))
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 17))
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>B : Symbol(B, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 19))
|
||||
|
||||
fnB: (b: SetOf<B>) => SetOf<C>,
|
||||
>fnB : Symbol(fnB, Decl(inferFromGenericFunctionReturnTypes2.ts, 42, 33))
|
||||
>b : Symbol(b, Decl(inferFromGenericFunctionReturnTypes2.ts, 43, 8))
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>B : Symbol(B, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 19))
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>C : Symbol(C, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 22))
|
||||
|
||||
fnC: (c: SetOf<C>) => SetOf<D>,
|
||||
>fnC : Symbol(fnC, Decl(inferFromGenericFunctionReturnTypes2.ts, 43, 33))
|
||||
>c : Symbol(c, Decl(inferFromGenericFunctionReturnTypes2.ts, 44, 8))
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>C : Symbol(C, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 22))
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>D : Symbol(D, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 25))
|
||||
|
||||
fnD: (c: SetOf<D>) => SetOf<E>,
|
||||
>fnD : Symbol(fnD, Decl(inferFromGenericFunctionReturnTypes2.ts, 44, 33))
|
||||
>c : Symbol(c, Decl(inferFromGenericFunctionReturnTypes2.ts, 45, 8))
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>D : Symbol(D, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 25))
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>E : Symbol(E, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 28))
|
||||
|
||||
):(x: SetOf<A>) => SetOf<E>;
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 46, 3))
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 17))
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>E : Symbol(E, Decl(inferFromGenericFunctionReturnTypes2.ts, 41, 28))
|
||||
|
||||
/* ... etc ... */
|
||||
function compose<T>(...fns: ((x: T) => T)[]): (x: T) => T {
|
||||
>compose : Symbol(compose, Decl(inferFromGenericFunctionReturnTypes2.ts, 39, 1), Decl(inferFromGenericFunctionReturnTypes2.ts, 46, 28))
|
||||
>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 48, 17))
|
||||
>fns : Symbol(fns, Decl(inferFromGenericFunctionReturnTypes2.ts, 48, 20))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 48, 30))
|
||||
>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 48, 17))
|
||||
>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 48, 17))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 48, 47))
|
||||
>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 48, 17))
|
||||
>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 48, 17))
|
||||
|
||||
return (x: T) => fns.reduce((prev, fn) => fn(prev), x);
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 49, 10))
|
||||
>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 48, 17))
|
||||
>fns.reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>fns : Symbol(fns, Decl(inferFromGenericFunctionReturnTypes2.ts, 48, 20))
|
||||
>reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>prev : Symbol(prev, Decl(inferFromGenericFunctionReturnTypes2.ts, 49, 31))
|
||||
>fn : Symbol(fn, Decl(inferFromGenericFunctionReturnTypes2.ts, 49, 36))
|
||||
>fn : Symbol(fn, Decl(inferFromGenericFunctionReturnTypes2.ts, 49, 36))
|
||||
>prev : Symbol(prev, Decl(inferFromGenericFunctionReturnTypes2.ts, 49, 31))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 49, 10))
|
||||
}
|
||||
|
||||
function map<A, B>(fn: (a: A) => B): (s: SetOf<A>) => SetOf<B> {
|
||||
>map : Symbol(map, Decl(inferFromGenericFunctionReturnTypes2.ts, 50, 1))
|
||||
>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 52, 13))
|
||||
>B : Symbol(B, Decl(inferFromGenericFunctionReturnTypes2.ts, 52, 15))
|
||||
>fn : Symbol(fn, Decl(inferFromGenericFunctionReturnTypes2.ts, 52, 19))
|
||||
>a : Symbol(a, Decl(inferFromGenericFunctionReturnTypes2.ts, 52, 24))
|
||||
>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 52, 13))
|
||||
>B : Symbol(B, Decl(inferFromGenericFunctionReturnTypes2.ts, 52, 15))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 52, 38))
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 52, 13))
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>B : Symbol(B, Decl(inferFromGenericFunctionReturnTypes2.ts, 52, 15))
|
||||
|
||||
return (a: SetOf<A>) => {
|
||||
>a : Symbol(a, Decl(inferFromGenericFunctionReturnTypes2.ts, 53, 10))
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 52, 13))
|
||||
|
||||
const b: SetOf<B> = new SetOf();
|
||||
>b : Symbol(b, Decl(inferFromGenericFunctionReturnTypes2.ts, 54, 9))
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>B : Symbol(B, Decl(inferFromGenericFunctionReturnTypes2.ts, 52, 15))
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
|
||||
a.forEach(x => b.add(fn(x)));
|
||||
>a.forEach : Symbol(SetOf.forEach, Decl(inferFromGenericFunctionReturnTypes2.ts, 34, 3))
|
||||
>a : Symbol(a, Decl(inferFromGenericFunctionReturnTypes2.ts, 53, 10))
|
||||
>forEach : Symbol(SetOf.forEach, Decl(inferFromGenericFunctionReturnTypes2.ts, 34, 3))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 55, 14))
|
||||
>b.add : Symbol(SetOf.add, Decl(inferFromGenericFunctionReturnTypes2.ts, 26, 14))
|
||||
>b : Symbol(b, Decl(inferFromGenericFunctionReturnTypes2.ts, 54, 9))
|
||||
>add : Symbol(SetOf.add, Decl(inferFromGenericFunctionReturnTypes2.ts, 26, 14))
|
||||
>fn : Symbol(fn, Decl(inferFromGenericFunctionReturnTypes2.ts, 52, 19))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 55, 14))
|
||||
|
||||
return b;
|
||||
>b : Symbol(b, Decl(inferFromGenericFunctionReturnTypes2.ts, 54, 9))
|
||||
}
|
||||
}
|
||||
|
||||
function filter<A>(predicate: (a: A) => boolean): (s: SetOf<A>) => SetOf<A> {
|
||||
>filter : Symbol(filter, Decl(inferFromGenericFunctionReturnTypes2.ts, 58, 1))
|
||||
>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 60, 16))
|
||||
>predicate : Symbol(predicate, Decl(inferFromGenericFunctionReturnTypes2.ts, 60, 19))
|
||||
>a : Symbol(a, Decl(inferFromGenericFunctionReturnTypes2.ts, 60, 31))
|
||||
>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 60, 16))
|
||||
>s : Symbol(s, Decl(inferFromGenericFunctionReturnTypes2.ts, 60, 51))
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 60, 16))
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 60, 16))
|
||||
|
||||
return (a: SetOf<A>) => {
|
||||
>a : Symbol(a, Decl(inferFromGenericFunctionReturnTypes2.ts, 61, 10))
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 60, 16))
|
||||
|
||||
const result = new SetOf<A>();
|
||||
>result : Symbol(result, Decl(inferFromGenericFunctionReturnTypes2.ts, 62, 9))
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
>A : Symbol(A, Decl(inferFromGenericFunctionReturnTypes2.ts, 60, 16))
|
||||
|
||||
a.forEach(x => {
|
||||
>a.forEach : Symbol(SetOf.forEach, Decl(inferFromGenericFunctionReturnTypes2.ts, 34, 3))
|
||||
>a : Symbol(a, Decl(inferFromGenericFunctionReturnTypes2.ts, 61, 10))
|
||||
>forEach : Symbol(SetOf.forEach, Decl(inferFromGenericFunctionReturnTypes2.ts, 34, 3))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 63, 14))
|
||||
|
||||
if (predicate(x)) result.add(x);
|
||||
>predicate : Symbol(predicate, Decl(inferFromGenericFunctionReturnTypes2.ts, 60, 19))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 63, 14))
|
||||
>result.add : Symbol(SetOf.add, Decl(inferFromGenericFunctionReturnTypes2.ts, 26, 14))
|
||||
>result : Symbol(result, Decl(inferFromGenericFunctionReturnTypes2.ts, 62, 9))
|
||||
>add : Symbol(SetOf.add, Decl(inferFromGenericFunctionReturnTypes2.ts, 26, 14))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 63, 14))
|
||||
|
||||
});
|
||||
return result;
|
||||
>result : Symbol(result, Decl(inferFromGenericFunctionReturnTypes2.ts, 62, 9))
|
||||
}
|
||||
}
|
||||
|
||||
const testSet = new SetOf<number>();
|
||||
>testSet : Symbol(testSet, Decl(inferFromGenericFunctionReturnTypes2.ts, 70, 5))
|
||||
>SetOf : Symbol(SetOf, Decl(inferFromGenericFunctionReturnTypes2.ts, 22, 64))
|
||||
|
||||
testSet.add(1);
|
||||
>testSet.add : Symbol(SetOf.add, Decl(inferFromGenericFunctionReturnTypes2.ts, 26, 14))
|
||||
>testSet : Symbol(testSet, Decl(inferFromGenericFunctionReturnTypes2.ts, 70, 5))
|
||||
>add : Symbol(SetOf.add, Decl(inferFromGenericFunctionReturnTypes2.ts, 26, 14))
|
||||
|
||||
testSet.add(2);
|
||||
>testSet.add : Symbol(SetOf.add, Decl(inferFromGenericFunctionReturnTypes2.ts, 26, 14))
|
||||
>testSet : Symbol(testSet, Decl(inferFromGenericFunctionReturnTypes2.ts, 70, 5))
|
||||
>add : Symbol(SetOf.add, Decl(inferFromGenericFunctionReturnTypes2.ts, 26, 14))
|
||||
|
||||
testSet.add(3);
|
||||
>testSet.add : Symbol(SetOf.add, Decl(inferFromGenericFunctionReturnTypes2.ts, 26, 14))
|
||||
>testSet : Symbol(testSet, Decl(inferFromGenericFunctionReturnTypes2.ts, 70, 5))
|
||||
>add : Symbol(SetOf.add, Decl(inferFromGenericFunctionReturnTypes2.ts, 26, 14))
|
||||
|
||||
const t1 = testSet.transform(
|
||||
>t1 : Symbol(t1, Decl(inferFromGenericFunctionReturnTypes2.ts, 75, 5))
|
||||
>testSet.transform : Symbol(SetOf.transform, Decl(inferFromGenericFunctionReturnTypes2.ts, 30, 3))
|
||||
>testSet : Symbol(testSet, Decl(inferFromGenericFunctionReturnTypes2.ts, 70, 5))
|
||||
>transform : Symbol(SetOf.transform, Decl(inferFromGenericFunctionReturnTypes2.ts, 30, 3))
|
||||
|
||||
compose(
|
||||
>compose : Symbol(compose, Decl(inferFromGenericFunctionReturnTypes2.ts, 39, 1), Decl(inferFromGenericFunctionReturnTypes2.ts, 46, 28))
|
||||
|
||||
filter(x => x % 1 === 0),
|
||||
>filter : Symbol(filter, Decl(inferFromGenericFunctionReturnTypes2.ts, 58, 1))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 77, 11))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 77, 11))
|
||||
|
||||
map(x => x + x),
|
||||
>map : Symbol(map, Decl(inferFromGenericFunctionReturnTypes2.ts, 50, 1))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 78, 8))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 78, 8))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 78, 8))
|
||||
|
||||
map(x => x + '!!!'),
|
||||
>map : Symbol(map, Decl(inferFromGenericFunctionReturnTypes2.ts, 50, 1))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 79, 8))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 79, 8))
|
||||
|
||||
map(x => x.toUpperCase())
|
||||
>map : Symbol(map, Decl(inferFromGenericFunctionReturnTypes2.ts, 50, 1))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 80, 8))
|
||||
>x.toUpperCase : Symbol(String.toUpperCase, Decl(lib.d.ts, --, --))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 80, 8))
|
||||
>toUpperCase : Symbol(String.toUpperCase, Decl(lib.d.ts, --, --))
|
||||
|
||||
)
|
||||
)
|
||||
|
||||
declare function identity<T>(x: T): T;
|
||||
>identity : Symbol(identity, Decl(inferFromGenericFunctionReturnTypes2.ts, 82, 1))
|
||||
>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 84, 26))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 84, 29))
|
||||
>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 84, 26))
|
||||
>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 84, 26))
|
||||
|
||||
const t2 = testSet.transform(
|
||||
>t2 : Symbol(t2, Decl(inferFromGenericFunctionReturnTypes2.ts, 86, 5))
|
||||
>testSet.transform : Symbol(SetOf.transform, Decl(inferFromGenericFunctionReturnTypes2.ts, 30, 3))
|
||||
>testSet : Symbol(testSet, Decl(inferFromGenericFunctionReturnTypes2.ts, 70, 5))
|
||||
>transform : Symbol(SetOf.transform, Decl(inferFromGenericFunctionReturnTypes2.ts, 30, 3))
|
||||
|
||||
compose(
|
||||
>compose : Symbol(compose, Decl(inferFromGenericFunctionReturnTypes2.ts, 39, 1), Decl(inferFromGenericFunctionReturnTypes2.ts, 46, 28))
|
||||
|
||||
filter(x => x % 1 === 0),
|
||||
>filter : Symbol(filter, Decl(inferFromGenericFunctionReturnTypes2.ts, 58, 1))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 88, 11))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 88, 11))
|
||||
|
||||
identity,
|
||||
>identity : Symbol(identity, Decl(inferFromGenericFunctionReturnTypes2.ts, 82, 1))
|
||||
|
||||
map(x => x + '!!!'),
|
||||
>map : Symbol(map, Decl(inferFromGenericFunctionReturnTypes2.ts, 50, 1))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 90, 8))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 90, 8))
|
||||
|
||||
map(x => x.toUpperCase())
|
||||
>map : Symbol(map, Decl(inferFromGenericFunctionReturnTypes2.ts, 50, 1))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 91, 8))
|
||||
>x.toUpperCase : Symbol(String.toUpperCase, Decl(lib.d.ts, --, --))
|
||||
>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 91, 8))
|
||||
>toUpperCase : Symbol(String.toUpperCase, Decl(lib.d.ts, --, --))
|
||||
|
||||
)
|
||||
)
|
||||
|
|
@ -0,0 +1,600 @@
|
|||
=== tests/cases/compiler/inferFromGenericFunctionReturnTypes2.ts ===
|
||||
type Mapper<T, U> = (x: T) => U;
|
||||
>Mapper : Mapper<T, U>
|
||||
>T : T
|
||||
>U : U
|
||||
>x : T
|
||||
>T : T
|
||||
>U : U
|
||||
|
||||
declare function wrap<T, U>(cb: Mapper<T, U>): Mapper<T, U>;
|
||||
>wrap : <T, U>(cb: Mapper<T, U>) => Mapper<T, U>
|
||||
>T : T
|
||||
>U : U
|
||||
>cb : Mapper<T, U>
|
||||
>Mapper : Mapper<T, U>
|
||||
>T : T
|
||||
>U : U
|
||||
>Mapper : Mapper<T, U>
|
||||
>T : T
|
||||
>U : U
|
||||
|
||||
declare function arrayize<T, U>(cb: Mapper<T, U>): Mapper<T, U[]>;
|
||||
>arrayize : <T, U>(cb: Mapper<T, U>) => Mapper<T, U[]>
|
||||
>T : T
|
||||
>U : U
|
||||
>cb : Mapper<T, U>
|
||||
>Mapper : Mapper<T, U>
|
||||
>T : T
|
||||
>U : U
|
||||
>Mapper : Mapper<T, U>
|
||||
>T : T
|
||||
>U : U
|
||||
|
||||
declare function combine<A, B, C>(f: (x: A) => B, g: (x: B) => C): (x: A) => C;
|
||||
>combine : <A, B, C>(f: (x: A) => B, g: (x: B) => C) => (x: A) => C
|
||||
>A : A
|
||||
>B : B
|
||||
>C : C
|
||||
>f : (x: A) => B
|
||||
>x : A
|
||||
>A : A
|
||||
>B : B
|
||||
>g : (x: B) => C
|
||||
>x : B
|
||||
>B : B
|
||||
>C : C
|
||||
>x : A
|
||||
>A : A
|
||||
>C : C
|
||||
|
||||
declare function foo(f: Mapper<string, number>): void;
|
||||
>foo : (f: Mapper<string, number>) => void
|
||||
>f : Mapper<string, number>
|
||||
>Mapper : Mapper<T, U>
|
||||
|
||||
let f1: Mapper<string, number> = s => s.length;
|
||||
>f1 : Mapper<string, number>
|
||||
>Mapper : Mapper<T, U>
|
||||
>s => s.length : (s: string) => number
|
||||
>s : string
|
||||
>s.length : number
|
||||
>s : string
|
||||
>length : number
|
||||
|
||||
let f2: Mapper<string, number> = wrap(s => s.length);
|
||||
>f2 : Mapper<string, number>
|
||||
>Mapper : Mapper<T, U>
|
||||
>wrap(s => s.length) : Mapper<string, number>
|
||||
>wrap : <T, U>(cb: Mapper<T, U>) => Mapper<T, U>
|
||||
>s => s.length : (s: string) => number
|
||||
>s : string
|
||||
>s.length : number
|
||||
>s : string
|
||||
>length : number
|
||||
|
||||
let f3: Mapper<string, number[]> = arrayize(wrap(s => s.length));
|
||||
>f3 : Mapper<string, number[]>
|
||||
>Mapper : Mapper<T, U>
|
||||
>arrayize(wrap(s => s.length)) : Mapper<string, number[]>
|
||||
>arrayize : <T, U>(cb: Mapper<T, U>) => Mapper<T, U[]>
|
||||
>wrap(s => s.length) : Mapper<string, number>
|
||||
>wrap : <T, U>(cb: Mapper<T, U>) => Mapper<T, U>
|
||||
>s => s.length : (s: string) => number
|
||||
>s : string
|
||||
>s.length : number
|
||||
>s : string
|
||||
>length : number
|
||||
|
||||
let f4: Mapper<string, boolean> = combine(wrap(s => s.length), wrap(n => n >= 10));
|
||||
>f4 : Mapper<string, boolean>
|
||||
>Mapper : Mapper<T, U>
|
||||
>combine(wrap(s => s.length), wrap(n => n >= 10)) : (x: string) => boolean
|
||||
>combine : <A, B, C>(f: (x: A) => B, g: (x: B) => C) => (x: A) => C
|
||||
>wrap(s => s.length) : Mapper<string, number>
|
||||
>wrap : <T, U>(cb: Mapper<T, U>) => Mapper<T, U>
|
||||
>s => s.length : (s: string) => number
|
||||
>s : string
|
||||
>s.length : number
|
||||
>s : string
|
||||
>length : number
|
||||
>wrap(n => n >= 10) : Mapper<number, boolean>
|
||||
>wrap : <T, U>(cb: Mapper<T, U>) => Mapper<T, U>
|
||||
>n => n >= 10 : (n: number) => boolean
|
||||
>n : number
|
||||
>n >= 10 : boolean
|
||||
>n : number
|
||||
>10 : 10
|
||||
|
||||
foo(wrap(s => s.length));
|
||||
>foo(wrap(s => s.length)) : void
|
||||
>foo : (f: Mapper<string, number>) => void
|
||||
>wrap(s => s.length) : Mapper<string, number>
|
||||
>wrap : <T, U>(cb: Mapper<T, U>) => Mapper<T, U>
|
||||
>s => s.length : (s: string) => number
|
||||
>s : string
|
||||
>s.length : number
|
||||
>s : string
|
||||
>length : number
|
||||
|
||||
let a1 = ["a", "b"].map(s => s.length);
|
||||
>a1 : number[]
|
||||
>["a", "b"].map(s => s.length) : number[]
|
||||
>["a", "b"].map : { <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U, U]; <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U, U]; <Z, U>(this: [string, string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U]; <Z, U>(this: [string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U]; <Z, U>(this: [string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U]; <Z, U>(this: [string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U): U[]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): U[]; <Z, U>(callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): U[]; }
|
||||
>["a", "b"] : string[]
|
||||
>"a" : "a"
|
||||
>"b" : "b"
|
||||
>map : { <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U, U]; <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U, U]; <Z, U>(this: [string, string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U]; <Z, U>(this: [string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U]; <Z, U>(this: [string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U]; <Z, U>(this: [string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U): U[]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): U[]; <Z, U>(callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): U[]; }
|
||||
>s => s.length : (this: void, s: string) => number
|
||||
>s : string
|
||||
>s.length : number
|
||||
>s : string
|
||||
>length : number
|
||||
|
||||
let a2 = ["a", "b"].map(wrap(s => s.length));
|
||||
>a2 : number[]
|
||||
>["a", "b"].map(wrap(s => s.length)) : number[]
|
||||
>["a", "b"].map : { <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U, U]; <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U, U]; <Z, U>(this: [string, string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U]; <Z, U>(this: [string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U]; <Z, U>(this: [string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U]; <Z, U>(this: [string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U): U[]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): U[]; <Z, U>(callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): U[]; }
|
||||
>["a", "b"] : string[]
|
||||
>"a" : "a"
|
||||
>"b" : "b"
|
||||
>map : { <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U, U]; <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U, U]; <Z, U>(this: [string, string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U]; <Z, U>(this: [string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U]; <Z, U>(this: [string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U]; <Z, U>(this: [string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U): U[]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): U[]; <Z, U>(callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): U[]; }
|
||||
>wrap(s => s.length) : Mapper<string, number>
|
||||
>wrap : <T, U>(cb: Mapper<T, U>) => Mapper<T, U>
|
||||
>s => s.length : (s: string) => number
|
||||
>s : string
|
||||
>s.length : number
|
||||
>s : string
|
||||
>length : number
|
||||
|
||||
let a3 = ["a", "b"].map(wrap(arrayize(s => s.length)));
|
||||
>a3 : number[][]
|
||||
>["a", "b"].map(wrap(arrayize(s => s.length))) : number[][]
|
||||
>["a", "b"].map : { <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U, U]; <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U, U]; <Z, U>(this: [string, string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U]; <Z, U>(this: [string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U]; <Z, U>(this: [string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U]; <Z, U>(this: [string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U): U[]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): U[]; <Z, U>(callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): U[]; }
|
||||
>["a", "b"] : string[]
|
||||
>"a" : "a"
|
||||
>"b" : "b"
|
||||
>map : { <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U, U]; <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U, U]; <Z, U>(this: [string, string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U]; <Z, U>(this: [string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U]; <Z, U>(this: [string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U]; <Z, U>(this: [string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U): U[]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): U[]; <Z, U>(callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): U[]; }
|
||||
>wrap(arrayize(s => s.length)) : Mapper<string, number[]>
|
||||
>wrap : <T, U>(cb: Mapper<T, U>) => Mapper<T, U>
|
||||
>arrayize(s => s.length) : Mapper<string, number[]>
|
||||
>arrayize : <T, U>(cb: Mapper<T, U>) => Mapper<T, U[]>
|
||||
>s => s.length : (s: string) => number
|
||||
>s : string
|
||||
>s.length : number
|
||||
>s : string
|
||||
>length : number
|
||||
|
||||
let a4 = ["a", "b"].map(combine(wrap(s => s.length), wrap(n => n > 10)));
|
||||
>a4 : boolean[]
|
||||
>["a", "b"].map(combine(wrap(s => s.length), wrap(n => n > 10))) : boolean[]
|
||||
>["a", "b"].map : { <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U, U]; <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U, U]; <Z, U>(this: [string, string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U]; <Z, U>(this: [string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U]; <Z, U>(this: [string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U]; <Z, U>(this: [string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U): U[]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): U[]; <Z, U>(callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): U[]; }
|
||||
>["a", "b"] : string[]
|
||||
>"a" : "a"
|
||||
>"b" : "b"
|
||||
>map : { <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U, U]; <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U, U]; <Z, U>(this: [string, string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U]; <Z, U>(this: [string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U]; <Z, U>(this: [string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U]; <Z, U>(this: [string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U): U[]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): U[]; <Z, U>(callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): U[]; }
|
||||
>combine(wrap(s => s.length), wrap(n => n > 10)) : (x: string) => boolean
|
||||
>combine : <A, B, C>(f: (x: A) => B, g: (x: B) => C) => (x: A) => C
|
||||
>wrap(s => s.length) : Mapper<string, number>
|
||||
>wrap : <T, U>(cb: Mapper<T, U>) => Mapper<T, U>
|
||||
>s => s.length : (s: string) => number
|
||||
>s : string
|
||||
>s.length : number
|
||||
>s : string
|
||||
>length : number
|
||||
>wrap(n => n > 10) : Mapper<number, boolean>
|
||||
>wrap : <T, U>(cb: Mapper<T, U>) => Mapper<T, U>
|
||||
>n => n > 10 : (n: number) => boolean
|
||||
>n : number
|
||||
>n > 10 : boolean
|
||||
>n : number
|
||||
>10 : 10
|
||||
|
||||
let a5 = ["a", "b"].map(combine(identity, wrap(s => s.length)));
|
||||
>a5 : number[]
|
||||
>["a", "b"].map(combine(identity, wrap(s => s.length))) : number[]
|
||||
>["a", "b"].map : { <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U, U]; <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U, U]; <Z, U>(this: [string, string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U]; <Z, U>(this: [string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U]; <Z, U>(this: [string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U]; <Z, U>(this: [string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U): U[]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): U[]; <Z, U>(callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): U[]; }
|
||||
>["a", "b"] : string[]
|
||||
>"a" : "a"
|
||||
>"b" : "b"
|
||||
>map : { <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U, U]; <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U, U]; <Z, U>(this: [string, string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U]; <Z, U>(this: [string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U]; <Z, U>(this: [string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U]; <Z, U>(this: [string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U): U[]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): U[]; <Z, U>(callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): U[]; }
|
||||
>combine(identity, wrap(s => s.length)) : (x: string) => number
|
||||
>combine : <A, B, C>(f: (x: A) => B, g: (x: B) => C) => (x: A) => C
|
||||
>identity : <T>(x: T) => T
|
||||
>wrap(s => s.length) : Mapper<string, number>
|
||||
>wrap : <T, U>(cb: Mapper<T, U>) => Mapper<T, U>
|
||||
>s => s.length : (s: string) => number
|
||||
>s : string
|
||||
>s.length : number
|
||||
>s : string
|
||||
>length : number
|
||||
|
||||
let a6 = ["a", "b"].map(combine(wrap(s => s.length), identity));
|
||||
>a6 : number[]
|
||||
>["a", "b"].map(combine(wrap(s => s.length), identity)) : number[]
|
||||
>["a", "b"].map : { <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U, U]; <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U, U]; <Z, U>(this: [string, string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U]; <Z, U>(this: [string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U]; <Z, U>(this: [string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U]; <Z, U>(this: [string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U): U[]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): U[]; <Z, U>(callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): U[]; }
|
||||
>["a", "b"] : string[]
|
||||
>"a" : "a"
|
||||
>"b" : "b"
|
||||
>map : { <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U, U]; <U>(this: [string, string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U, U]; <Z, U>(this: [string, string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U, U]; <U>(this: [string, string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U, U]; <Z, U>(this: [string, string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U, U]; <U>(this: [string, string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U, U]; <Z, U>(this: [string, string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U): [U, U]; <U>(this: [string, string], callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): [U, U]; <Z, U>(this: [string, string], callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): [U, U]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U): U[]; <U>(callbackfn: (this: void, value: string, index: number, array: string[]) => U, thisArg: undefined): U[]; <Z, U>(callbackfn: (this: Z, value: string, index: number, array: string[]) => U, thisArg: Z): U[]; }
|
||||
>combine(wrap(s => s.length), identity) : (x: string) => number
|
||||
>combine : <A, B, C>(f: (x: A) => B, g: (x: B) => C) => (x: A) => C
|
||||
>wrap(s => s.length) : Mapper<string, number>
|
||||
>wrap : <T, U>(cb: Mapper<T, U>) => Mapper<T, U>
|
||||
>s => s.length : (s: string) => number
|
||||
>s : string
|
||||
>s.length : number
|
||||
>s : string
|
||||
>length : number
|
||||
>identity : <T>(x: T) => T
|
||||
|
||||
// This is a contrived class. We could do the same thing with Observables, etc.
|
||||
class SetOf<A> {
|
||||
>SetOf : SetOf<A>
|
||||
>A : A
|
||||
|
||||
_store: A[];
|
||||
>_store : A[]
|
||||
>A : A
|
||||
|
||||
add(a: A) {
|
||||
>add : (a: A) => void
|
||||
>a : A
|
||||
>A : A
|
||||
|
||||
this._store.push(a);
|
||||
>this._store.push(a) : number
|
||||
>this._store.push : (...items: A[]) => number
|
||||
>this._store : A[]
|
||||
>this : this
|
||||
>_store : A[]
|
||||
>push : (...items: A[]) => number
|
||||
>a : A
|
||||
}
|
||||
|
||||
transform<B>(transformer: (a: SetOf<A>) => SetOf<B>): SetOf<B> {
|
||||
>transform : <B>(transformer: (a: SetOf<A>) => SetOf<B>) => SetOf<B>
|
||||
>B : B
|
||||
>transformer : (a: SetOf<A>) => SetOf<B>
|
||||
>a : SetOf<A>
|
||||
>SetOf : SetOf<A>
|
||||
>A : A
|
||||
>SetOf : SetOf<A>
|
||||
>B : B
|
||||
>SetOf : SetOf<A>
|
||||
>B : B
|
||||
|
||||
return transformer(this);
|
||||
>transformer(this) : SetOf<B>
|
||||
>transformer : (a: SetOf<A>) => SetOf<B>
|
||||
>this : this
|
||||
}
|
||||
|
||||
forEach(fn: (a: A, index: number) => void) {
|
||||
>forEach : (fn: (a: A, index: number) => void) => void
|
||||
>fn : (a: A, index: number) => void
|
||||
>a : A
|
||||
>A : A
|
||||
>index : number
|
||||
|
||||
this._store.forEach((a, i) => fn(a, i));
|
||||
>this._store.forEach((a, i) => fn(a, i)) : void
|
||||
>this._store.forEach : { (callbackfn: (this: void, value: A, index: number, array: A[]) => void): void; (callbackfn: (this: void, value: A, index: number, array: A[]) => void, thisArg: undefined): void; <Z>(callbackfn: (this: Z, value: A, index: number, array: A[]) => void, thisArg: Z): void; }
|
||||
>this._store : A[]
|
||||
>this : this
|
||||
>_store : A[]
|
||||
>forEach : { (callbackfn: (this: void, value: A, index: number, array: A[]) => void): void; (callbackfn: (this: void, value: A, index: number, array: A[]) => void, thisArg: undefined): void; <Z>(callbackfn: (this: Z, value: A, index: number, array: A[]) => void, thisArg: Z): void; }
|
||||
>(a, i) => fn(a, i) : (this: void, a: A, i: number) => void
|
||||
>a : A
|
||||
>i : number
|
||||
>fn(a, i) : void
|
||||
>fn : (a: A, index: number) => void
|
||||
>a : A
|
||||
>i : number
|
||||
}
|
||||
}
|
||||
|
||||
function compose<A, B, C, D, E>(
|
||||
>compose : <A, B, C, D, E>(fnA: (a: SetOf<A>) => SetOf<B>, fnB: (b: SetOf<B>) => SetOf<C>, fnC: (c: SetOf<C>) => SetOf<D>, fnD: (c: SetOf<D>) => SetOf<E>) => (x: SetOf<A>) => SetOf<E>
|
||||
>A : A
|
||||
>B : B
|
||||
>C : C
|
||||
>D : D
|
||||
>E : E
|
||||
|
||||
fnA: (a: SetOf<A>) => SetOf<B>,
|
||||
>fnA : (a: SetOf<A>) => SetOf<B>
|
||||
>a : SetOf<A>
|
||||
>SetOf : SetOf<A>
|
||||
>A : A
|
||||
>SetOf : SetOf<A>
|
||||
>B : B
|
||||
|
||||
fnB: (b: SetOf<B>) => SetOf<C>,
|
||||
>fnB : (b: SetOf<B>) => SetOf<C>
|
||||
>b : SetOf<B>
|
||||
>SetOf : SetOf<A>
|
||||
>B : B
|
||||
>SetOf : SetOf<A>
|
||||
>C : C
|
||||
|
||||
fnC: (c: SetOf<C>) => SetOf<D>,
|
||||
>fnC : (c: SetOf<C>) => SetOf<D>
|
||||
>c : SetOf<C>
|
||||
>SetOf : SetOf<A>
|
||||
>C : C
|
||||
>SetOf : SetOf<A>
|
||||
>D : D
|
||||
|
||||
fnD: (c: SetOf<D>) => SetOf<E>,
|
||||
>fnD : (c: SetOf<D>) => SetOf<E>
|
||||
>c : SetOf<D>
|
||||
>SetOf : SetOf<A>
|
||||
>D : D
|
||||
>SetOf : SetOf<A>
|
||||
>E : E
|
||||
|
||||
):(x: SetOf<A>) => SetOf<E>;
|
||||
>x : SetOf<A>
|
||||
>SetOf : SetOf<A>
|
||||
>A : A
|
||||
>SetOf : SetOf<A>
|
||||
>E : E
|
||||
|
||||
/* ... etc ... */
|
||||
function compose<T>(...fns: ((x: T) => T)[]): (x: T) => T {
|
||||
>compose : <A, B, C, D, E>(fnA: (a: SetOf<A>) => SetOf<B>, fnB: (b: SetOf<B>) => SetOf<C>, fnC: (c: SetOf<C>) => SetOf<D>, fnD: (c: SetOf<D>) => SetOf<E>) => (x: SetOf<A>) => SetOf<E>
|
||||
>T : T
|
||||
>fns : ((x: T) => T)[]
|
||||
>x : T
|
||||
>T : T
|
||||
>T : T
|
||||
>x : T
|
||||
>T : T
|
||||
>T : T
|
||||
|
||||
return (x: T) => fns.reduce((prev, fn) => fn(prev), x);
|
||||
>(x: T) => fns.reduce((prev, fn) => fn(prev), x) : (x: T) => T
|
||||
>x : T
|
||||
>T : T
|
||||
>fns.reduce((prev, fn) => fn(prev), x) : T
|
||||
>fns.reduce : { (callbackfn: (previousValue: (x: T) => T, currentValue: (x: T) => T, currentIndex: number, array: ((x: T) => T)[]) => (x: T) => T, initialValue?: (x: T) => T): (x: T) => T; <U>(callbackfn: (previousValue: U, currentValue: (x: T) => T, currentIndex: number, array: ((x: T) => T)[]) => U, initialValue: U): U; }
|
||||
>fns : ((x: T) => T)[]
|
||||
>reduce : { (callbackfn: (previousValue: (x: T) => T, currentValue: (x: T) => T, currentIndex: number, array: ((x: T) => T)[]) => (x: T) => T, initialValue?: (x: T) => T): (x: T) => T; <U>(callbackfn: (previousValue: U, currentValue: (x: T) => T, currentIndex: number, array: ((x: T) => T)[]) => U, initialValue: U): U; }
|
||||
>(prev, fn) => fn(prev) : (prev: T, fn: (x: T) => T) => T
|
||||
>prev : T
|
||||
>fn : (x: T) => T
|
||||
>fn(prev) : T
|
||||
>fn : (x: T) => T
|
||||
>prev : T
|
||||
>x : T
|
||||
}
|
||||
|
||||
function map<A, B>(fn: (a: A) => B): (s: SetOf<A>) => SetOf<B> {
|
||||
>map : <A, B>(fn: (a: A) => B) => (s: SetOf<A>) => SetOf<B>
|
||||
>A : A
|
||||
>B : B
|
||||
>fn : (a: A) => B
|
||||
>a : A
|
||||
>A : A
|
||||
>B : B
|
||||
>s : SetOf<A>
|
||||
>SetOf : SetOf<A>
|
||||
>A : A
|
||||
>SetOf : SetOf<A>
|
||||
>B : B
|
||||
|
||||
return (a: SetOf<A>) => {
|
||||
>(a: SetOf<A>) => { const b: SetOf<B> = new SetOf(); a.forEach(x => b.add(fn(x))); return b; } : (a: SetOf<A>) => SetOf<B>
|
||||
>a : SetOf<A>
|
||||
>SetOf : SetOf<A>
|
||||
>A : A
|
||||
|
||||
const b: SetOf<B> = new SetOf();
|
||||
>b : SetOf<B>
|
||||
>SetOf : SetOf<A>
|
||||
>B : B
|
||||
>new SetOf() : SetOf<B>
|
||||
>SetOf : typeof SetOf
|
||||
|
||||
a.forEach(x => b.add(fn(x)));
|
||||
>a.forEach(x => b.add(fn(x))) : void
|
||||
>a.forEach : (fn: (a: A, index: number) => void) => void
|
||||
>a : SetOf<A>
|
||||
>forEach : (fn: (a: A, index: number) => void) => void
|
||||
>x => b.add(fn(x)) : (x: A) => void
|
||||
>x : A
|
||||
>b.add(fn(x)) : void
|
||||
>b.add : (a: B) => void
|
||||
>b : SetOf<B>
|
||||
>add : (a: B) => void
|
||||
>fn(x) : B
|
||||
>fn : (a: A) => B
|
||||
>x : A
|
||||
|
||||
return b;
|
||||
>b : SetOf<B>
|
||||
}
|
||||
}
|
||||
|
||||
function filter<A>(predicate: (a: A) => boolean): (s: SetOf<A>) => SetOf<A> {
|
||||
>filter : <A>(predicate: (a: A) => boolean) => (s: SetOf<A>) => SetOf<A>
|
||||
>A : A
|
||||
>predicate : (a: A) => boolean
|
||||
>a : A
|
||||
>A : A
|
||||
>s : SetOf<A>
|
||||
>SetOf : SetOf<A>
|
||||
>A : A
|
||||
>SetOf : SetOf<A>
|
||||
>A : A
|
||||
|
||||
return (a: SetOf<A>) => {
|
||||
>(a: SetOf<A>) => { const result = new SetOf<A>(); a.forEach(x => { if (predicate(x)) result.add(x); }); return result; } : (a: SetOf<A>) => SetOf<A>
|
||||
>a : SetOf<A>
|
||||
>SetOf : SetOf<A>
|
||||
>A : A
|
||||
|
||||
const result = new SetOf<A>();
|
||||
>result : SetOf<A>
|
||||
>new SetOf<A>() : SetOf<A>
|
||||
>SetOf : typeof SetOf
|
||||
>A : A
|
||||
|
||||
a.forEach(x => {
|
||||
>a.forEach(x => { if (predicate(x)) result.add(x); }) : void
|
||||
>a.forEach : (fn: (a: A, index: number) => void) => void
|
||||
>a : SetOf<A>
|
||||
>forEach : (fn: (a: A, index: number) => void) => void
|
||||
>x => { if (predicate(x)) result.add(x); } : (x: A) => void
|
||||
>x : A
|
||||
|
||||
if (predicate(x)) result.add(x);
|
||||
>predicate(x) : boolean
|
||||
>predicate : (a: A) => boolean
|
||||
>x : A
|
||||
>result.add(x) : void
|
||||
>result.add : (a: A) => void
|
||||
>result : SetOf<A>
|
||||
>add : (a: A) => void
|
||||
>x : A
|
||||
|
||||
});
|
||||
return result;
|
||||
>result : SetOf<A>
|
||||
}
|
||||
}
|
||||
|
||||
const testSet = new SetOf<number>();
|
||||
>testSet : SetOf<number>
|
||||
>new SetOf<number>() : SetOf<number>
|
||||
>SetOf : typeof SetOf
|
||||
|
||||
testSet.add(1);
|
||||
>testSet.add(1) : void
|
||||
>testSet.add : (a: number) => void
|
||||
>testSet : SetOf<number>
|
||||
>add : (a: number) => void
|
||||
>1 : 1
|
||||
|
||||
testSet.add(2);
|
||||
>testSet.add(2) : void
|
||||
>testSet.add : (a: number) => void
|
||||
>testSet : SetOf<number>
|
||||
>add : (a: number) => void
|
||||
>2 : 2
|
||||
|
||||
testSet.add(3);
|
||||
>testSet.add(3) : void
|
||||
>testSet.add : (a: number) => void
|
||||
>testSet : SetOf<number>
|
||||
>add : (a: number) => void
|
||||
>3 : 3
|
||||
|
||||
const t1 = testSet.transform(
|
||||
>t1 : SetOf<string>
|
||||
>testSet.transform( compose( filter(x => x % 1 === 0), map(x => x + x), map(x => x + '!!!'), map(x => x.toUpperCase()) )) : SetOf<string>
|
||||
>testSet.transform : <B>(transformer: (a: SetOf<number>) => SetOf<B>) => SetOf<B>
|
||||
>testSet : SetOf<number>
|
||||
>transform : <B>(transformer: (a: SetOf<number>) => SetOf<B>) => SetOf<B>
|
||||
|
||||
compose(
|
||||
>compose( filter(x => x % 1 === 0), map(x => x + x), map(x => x + '!!!'), map(x => x.toUpperCase()) ) : (x: SetOf<number>) => SetOf<string>
|
||||
>compose : <A, B, C, D, E>(fnA: (a: SetOf<A>) => SetOf<B>, fnB: (b: SetOf<B>) => SetOf<C>, fnC: (c: SetOf<C>) => SetOf<D>, fnD: (c: SetOf<D>) => SetOf<E>) => (x: SetOf<A>) => SetOf<E>
|
||||
|
||||
filter(x => x % 1 === 0),
|
||||
>filter(x => x % 1 === 0) : (s: SetOf<number>) => SetOf<number>
|
||||
>filter : <A>(predicate: (a: A) => boolean) => (s: SetOf<A>) => SetOf<A>
|
||||
>x => x % 1 === 0 : (x: number) => boolean
|
||||
>x : number
|
||||
>x % 1 === 0 : boolean
|
||||
>x % 1 : number
|
||||
>x : number
|
||||
>1 : 1
|
||||
>0 : 0
|
||||
|
||||
map(x => x + x),
|
||||
>map(x => x + x) : (s: SetOf<number>) => SetOf<number>
|
||||
>map : <A, B>(fn: (a: A) => B) => (s: SetOf<A>) => SetOf<B>
|
||||
>x => x + x : (x: number) => number
|
||||
>x : number
|
||||
>x + x : number
|
||||
>x : number
|
||||
>x : number
|
||||
|
||||
map(x => x + '!!!'),
|
||||
>map(x => x + '!!!') : (s: SetOf<number>) => SetOf<string>
|
||||
>map : <A, B>(fn: (a: A) => B) => (s: SetOf<A>) => SetOf<B>
|
||||
>x => x + '!!!' : (x: number) => string
|
||||
>x : number
|
||||
>x + '!!!' : string
|
||||
>x : number
|
||||
>'!!!' : "!!!"
|
||||
|
||||
map(x => x.toUpperCase())
|
||||
>map(x => x.toUpperCase()) : (s: SetOf<string>) => SetOf<string>
|
||||
>map : <A, B>(fn: (a: A) => B) => (s: SetOf<A>) => SetOf<B>
|
||||
>x => x.toUpperCase() : (x: string) => string
|
||||
>x : string
|
||||
>x.toUpperCase() : string
|
||||
>x.toUpperCase : () => string
|
||||
>x : string
|
||||
>toUpperCase : () => string
|
||||
|
||||
)
|
||||
)
|
||||
|
||||
declare function identity<T>(x: T): T;
|
||||
>identity : <T>(x: T) => T
|
||||
>T : T
|
||||
>x : T
|
||||
>T : T
|
||||
>T : T
|
||||
|
||||
const t2 = testSet.transform(
|
||||
>t2 : SetOf<string>
|
||||
>testSet.transform( compose( filter(x => x % 1 === 0), identity, map(x => x + '!!!'), map(x => x.toUpperCase()) )) : SetOf<string>
|
||||
>testSet.transform : <B>(transformer: (a: SetOf<number>) => SetOf<B>) => SetOf<B>
|
||||
>testSet : SetOf<number>
|
||||
>transform : <B>(transformer: (a: SetOf<number>) => SetOf<B>) => SetOf<B>
|
||||
|
||||
compose(
|
||||
>compose( filter(x => x % 1 === 0), identity, map(x => x + '!!!'), map(x => x.toUpperCase()) ) : (x: SetOf<number>) => SetOf<string>
|
||||
>compose : <A, B, C, D, E>(fnA: (a: SetOf<A>) => SetOf<B>, fnB: (b: SetOf<B>) => SetOf<C>, fnC: (c: SetOf<C>) => SetOf<D>, fnD: (c: SetOf<D>) => SetOf<E>) => (x: SetOf<A>) => SetOf<E>
|
||||
|
||||
filter(x => x % 1 === 0),
|
||||
>filter(x => x % 1 === 0) : (s: SetOf<number>) => SetOf<number>
|
||||
>filter : <A>(predicate: (a: A) => boolean) => (s: SetOf<A>) => SetOf<A>
|
||||
>x => x % 1 === 0 : (x: number) => boolean
|
||||
>x : number
|
||||
>x % 1 === 0 : boolean
|
||||
>x % 1 : number
|
||||
>x : number
|
||||
>1 : 1
|
||||
>0 : 0
|
||||
|
||||
identity,
|
||||
>identity : <T>(x: T) => T
|
||||
|
||||
map(x => x + '!!!'),
|
||||
>map(x => x + '!!!') : (s: SetOf<number>) => SetOf<string>
|
||||
>map : <A, B>(fn: (a: A) => B) => (s: SetOf<A>) => SetOf<B>
|
||||
>x => x + '!!!' : (x: number) => string
|
||||
>x : number
|
||||
>x + '!!!' : string
|
||||
>x : number
|
||||
>'!!!' : "!!!"
|
||||
|
||||
map(x => x.toUpperCase())
|
||||
>map(x => x.toUpperCase()) : (s: SetOf<string>) => SetOf<string>
|
||||
>map : <A, B>(fn: (a: A) => B) => (s: SetOf<A>) => SetOf<B>
|
||||
>x => x.toUpperCase() : (x: string) => string
|
||||
>x : string
|
||||
>x.toUpperCase() : string
|
||||
>x.toUpperCase : () => string
|
||||
>x : string
|
||||
>toUpperCase : () => string
|
||||
|
||||
)
|
||||
)
|
||||
|
|
@ -1,9 +1,7 @@
|
|||
tests/cases/compiler/recursiveTypeComparison2.ts(13,80): error TS2304: Cannot find name 'StateValue'.
|
||||
tests/cases/compiler/recursiveTypeComparison2.ts(30,5): error TS2322: Type 'Bus<{}>' is not assignable to type 'Bus<number>'.
|
||||
Type '{}' is not assignable to type 'number'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/recursiveTypeComparison2.ts (2 errors) ====
|
||||
==== tests/cases/compiler/recursiveTypeComparison2.ts (1 errors) ====
|
||||
// Before fix this would cause compiler to hang (#1170)
|
||||
|
||||
declare module Bacon {
|
||||
|
@ -35,7 +33,4 @@ tests/cases/compiler/recursiveTypeComparison2.ts(30,5): error TS2322: Type 'Bus<
|
|||
var Bus: new <T>() => Bus<T>;
|
||||
}
|
||||
|
||||
var stuck: Bacon.Bus<number> = new Bacon.Bus();
|
||||
~~~~~
|
||||
!!! error TS2322: Type 'Bus<{}>' is not assignable to type 'Bus<number>'.
|
||||
!!! error TS2322: Type '{}' is not assignable to type 'number'.
|
||||
var stuck: Bacon.Bus<number> = new Bacon.Bus();
|
70
tests/cases/compiler/inferFromGenericFunctionReturnTypes1.ts
Normal file
70
tests/cases/compiler/inferFromGenericFunctionReturnTypes1.ts
Normal file
|
@ -0,0 +1,70 @@
|
|||
// Repro from #15680
|
||||
|
||||
// This is a contrived class. We could do the same thing with Observables, etc.
|
||||
class SetOf<A> {
|
||||
_store: A[];
|
||||
|
||||
add(a: A) {
|
||||
this._store.push(a);
|
||||
}
|
||||
|
||||
transform<B>(transformer: (a: SetOf<A>) => SetOf<B>): SetOf<B> {
|
||||
return transformer(this);
|
||||
}
|
||||
|
||||
forEach(fn: (a: A, index: number) => void) {
|
||||
this._store.forEach((a, i) => fn(a, i));
|
||||
}
|
||||
}
|
||||
|
||||
function compose<A, B, C, D, E>(
|
||||
fnA: (a: SetOf<A>) => SetOf<B>,
|
||||
fnB: (b: SetOf<B>) => SetOf<C>,
|
||||
fnC: (c: SetOf<C>) => SetOf<D>,
|
||||
fnD: (c: SetOf<D>) => SetOf<E>,
|
||||
):(x: SetOf<A>) => SetOf<E>;
|
||||
/* ... etc ... */
|
||||
function compose<T>(...fns: ((x: T) => T)[]): (x: T) => T {
|
||||
return (x: T) => fns.reduce((prev, fn) => fn(prev), x);
|
||||
}
|
||||
|
||||
function map<A, B>(fn: (a: A) => B): (s: SetOf<A>) => SetOf<B> {
|
||||
return (a: SetOf<A>) => {
|
||||
const b: SetOf<B> = new SetOf();
|
||||
a.forEach(x => b.add(fn(x)));
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
function filter<A>(predicate: (a: A) => boolean): (s: SetOf<A>) => SetOf<A> {
|
||||
return (a: SetOf<A>) => {
|
||||
const result = new SetOf<A>();
|
||||
a.forEach(x => {
|
||||
if (predicate(x)) result.add(x);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
const testSet = new SetOf<number>();
|
||||
testSet.add(1);
|
||||
testSet.add(2);
|
||||
testSet.add(3);
|
||||
|
||||
testSet.transform(
|
||||
compose(
|
||||
filter(x => x % 1 === 0),
|
||||
map(x => x + x),
|
||||
map(x => x + '!!!'),
|
||||
map(x => x.toUpperCase())
|
||||
)
|
||||
)
|
||||
|
||||
testSet.transform(
|
||||
compose(
|
||||
filter(x => x % 1 === 0),
|
||||
map(x => x + x),
|
||||
map(x => 123), // Whoops a bug
|
||||
map(x => x.toUpperCase()) // causes an error!
|
||||
)
|
||||
)
|
94
tests/cases/compiler/inferFromGenericFunctionReturnTypes2.ts
Normal file
94
tests/cases/compiler/inferFromGenericFunctionReturnTypes2.ts
Normal file
|
@ -0,0 +1,94 @@
|
|||
type Mapper<T, U> = (x: T) => U;
|
||||
|
||||
declare function wrap<T, U>(cb: Mapper<T, U>): Mapper<T, U>;
|
||||
|
||||
declare function arrayize<T, U>(cb: Mapper<T, U>): Mapper<T, U[]>;
|
||||
|
||||
declare function combine<A, B, C>(f: (x: A) => B, g: (x: B) => C): (x: A) => C;
|
||||
|
||||
declare function foo(f: Mapper<string, number>): void;
|
||||
|
||||
let f1: Mapper<string, number> = s => s.length;
|
||||
let f2: Mapper<string, number> = wrap(s => s.length);
|
||||
let f3: Mapper<string, number[]> = arrayize(wrap(s => s.length));
|
||||
let f4: Mapper<string, boolean> = combine(wrap(s => s.length), wrap(n => n >= 10));
|
||||
|
||||
foo(wrap(s => s.length));
|
||||
|
||||
let a1 = ["a", "b"].map(s => s.length);
|
||||
let a2 = ["a", "b"].map(wrap(s => s.length));
|
||||
let a3 = ["a", "b"].map(wrap(arrayize(s => s.length)));
|
||||
let a4 = ["a", "b"].map(combine(wrap(s => s.length), wrap(n => n > 10)));
|
||||
let a5 = ["a", "b"].map(combine(identity, wrap(s => s.length)));
|
||||
let a6 = ["a", "b"].map(combine(wrap(s => s.length), identity));
|
||||
|
||||
// This is a contrived class. We could do the same thing with Observables, etc.
|
||||
class SetOf<A> {
|
||||
_store: A[];
|
||||
|
||||
add(a: A) {
|
||||
this._store.push(a);
|
||||
}
|
||||
|
||||
transform<B>(transformer: (a: SetOf<A>) => SetOf<B>): SetOf<B> {
|
||||
return transformer(this);
|
||||
}
|
||||
|
||||
forEach(fn: (a: A, index: number) => void) {
|
||||
this._store.forEach((a, i) => fn(a, i));
|
||||
}
|
||||
}
|
||||
|
||||
function compose<A, B, C, D, E>(
|
||||
fnA: (a: SetOf<A>) => SetOf<B>,
|
||||
fnB: (b: SetOf<B>) => SetOf<C>,
|
||||
fnC: (c: SetOf<C>) => SetOf<D>,
|
||||
fnD: (c: SetOf<D>) => SetOf<E>,
|
||||
):(x: SetOf<A>) => SetOf<E>;
|
||||
/* ... etc ... */
|
||||
function compose<T>(...fns: ((x: T) => T)[]): (x: T) => T {
|
||||
return (x: T) => fns.reduce((prev, fn) => fn(prev), x);
|
||||
}
|
||||
|
||||
function map<A, B>(fn: (a: A) => B): (s: SetOf<A>) => SetOf<B> {
|
||||
return (a: SetOf<A>) => {
|
||||
const b: SetOf<B> = new SetOf();
|
||||
a.forEach(x => b.add(fn(x)));
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
function filter<A>(predicate: (a: A) => boolean): (s: SetOf<A>) => SetOf<A> {
|
||||
return (a: SetOf<A>) => {
|
||||
const result = new SetOf<A>();
|
||||
a.forEach(x => {
|
||||
if (predicate(x)) result.add(x);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
const testSet = new SetOf<number>();
|
||||
testSet.add(1);
|
||||
testSet.add(2);
|
||||
testSet.add(3);
|
||||
|
||||
const t1 = testSet.transform(
|
||||
compose(
|
||||
filter(x => x % 1 === 0),
|
||||
map(x => x + x),
|
||||
map(x => x + '!!!'),
|
||||
map(x => x.toUpperCase())
|
||||
)
|
||||
)
|
||||
|
||||
declare function identity<T>(x: T): T;
|
||||
|
||||
const t2 = testSet.transform(
|
||||
compose(
|
||||
filter(x => x % 1 === 0),
|
||||
identity,
|
||||
map(x => x + '!!!'),
|
||||
map(x => x.toUpperCase())
|
||||
)
|
||||
)
|
|
@ -1,48 +1,48 @@
|
|||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
////interface Collection<T, U> {
|
||||
//// length: number;
|
||||
//// add(x: T, y: U): void ;
|
||||
//// remove(x: T, y: U): boolean;
|
||||
////}
|
||||
//// length: number;
|
||||
//// add(x: T, y: U): void ;
|
||||
//// remove(x: T, y: U): boolean;
|
||||
////}
|
||||
////
|
||||
////interface Combinators {
|
||||
//// map<T, U, V>(c: Collection<T, U>, f: (x: T, y: U) => V): Collection<T, V>;
|
||||
//// map<T, U>(c: Collection<T, U>, f: (x: T, y: U) => any): Collection<any, any>;
|
||||
////}
|
||||
//// map<T, U, V>(c: Collection<T, U>, f: (x: T, y: U) => V): Collection<T, V>;
|
||||
//// map<T, U>(c: Collection<T, U>, f: (x: T, y: U) => any): Collection<any, any>;
|
||||
////}
|
||||
////
|
||||
////class A {
|
||||
//// foo<T>(): T { return null; }
|
||||
////}
|
||||
//// foo<T>(): T { return null; }
|
||||
////}
|
||||
////
|
||||
////class B<T> {
|
||||
//// foo(x: T): T { return null; }
|
||||
////}
|
||||
//// foo(x: T): T { return null; }
|
||||
////}
|
||||
////
|
||||
////var c1: Collection<any, any>;
|
||||
////var c2: Collection<number, string>;
|
||||
////var c3: Collection<Collection<number, number>, string>;
|
||||
////var c4: Collection<number, A>;
|
||||
////var c5: Collection<number, B<any>>;
|
||||
////}
|
||||
////
|
||||
////var _: Combinators;
|
||||
////// param help on open paren for arg 2 should show 'number' not T or 'any'
|
||||
////// x should be contextually typed to number
|
||||
////var rf1 = (x: number, y: string) => { return x.toFixed() };
|
||||
////var rf2 = (x: Collection<number, number>, y: string) => { return x.length };
|
||||
////var rf3 = (x: number, y: A) => { return y.foo() };
|
||||
////}
|
||||
////
|
||||
////var /*9*/r1a = _.map/*1c*/(c2, (/*1a*/x, /*1b*/y) => { return x.toFixed() });
|
||||
////var /*10*/r1b = _.map(c2, rf1);
|
||||
////}
|
||||
////
|
||||
////var /*11*/r2a = _.map(c3, (/*2a*/x, /*2b*/y) => { return x.length });
|
||||
////var /*12*/r2b = _.map(c3, rf2);
|
||||
////}
|
||||
////
|
||||
////var /*13*/r3a = _.map(c4, (/*3a*/x, /*3b*/y) => { return y.foo() });
|
||||
////var /*14*/r3b = _.map(c4, rf3);
|
||||
////}
|
||||
////
|
||||
////var /*15*/r4a = _.map(c5, (/*4a*/x, /*4b*/y) => { return y.foo() });
|
||||
////}
|
||||
////
|
||||
////var /*17*/r5a = _.map<number, string, Date>(c2, /*17error1*/(/*5a*/x, /*5b*/y) => { return x.toFixed() }/*17error2*/);
|
||||
////var rf1b = (x: number, y: string) => { return new Date() };
|
||||
////var /*18*/r5b = _.map<number, string, Date>(c2, rf1b);
|
||||
|
@ -51,7 +51,7 @@
|
|||
////var rf2b = (x: Collection<number, number>, y: string) => { return new Date(); };
|
||||
////var /*20*/r6b = _.map<Collection<number, number>, string, Date>(c3, rf2b);
|
||||
////
|
||||
////var /*21*/r7a = _.map<number, A, string>(c4, /*21error1*/(/*7a*/x,/*7b*/y) => { return y.foo() }/*21error2*/);
|
||||
////var /*21*/r7a = _.map<number, A, string>(c4, (/*7a*/x,/*7b*/y) => { return y.foo() });
|
||||
////var /*22*/r7b = _.map<number, A, string>(c4, /*22error1*/rf3/*22error2*/);
|
||||
////
|
||||
////var /*23*/r8a = _.map<number, /*error1*/B/*error2*/, string>(c5, (/*8a*/x,/*8b*/y) => { return y.foo() });
|
||||
|
@ -89,5 +89,4 @@ verify.quickInfos({
|
|||
|
||||
verify.errorExistsBetweenMarkers('error1', 'error2');
|
||||
verify.errorExistsBetweenMarkers('17error1', '17error2');
|
||||
verify.errorExistsBetweenMarkers('21error1', '21error2');
|
||||
verify.errorExistsBetweenMarkers('22error1', '22error2');
|
Loading…
Reference in a new issue