diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index a7e94da09d995..e38d91445d517 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -3366,6 +3366,7 @@ namespace ts { case SyntaxKind.ThisType: case SyntaxKind.TypeOperator: case SyntaxKind.IndexedAccessType: + case SyntaxKind.TypeCall: case SyntaxKind.MappedType: case SyntaxKind.LiteralType: case SyntaxKind.NamespaceExportDeclaration: diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 088cb4bb851ed..58482dbabce12 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2537,6 +2537,11 @@ namespace ts { const indexTypeNode = typeToTypeNodeHelper((type).indexType, context); return createIndexedAccessTypeNode(objectTypeNode, indexTypeNode); } + if (type.flags & TypeFlags.TypeCall) { + const fnNode = typeToTypeNodeHelper((type).function, context); + const argNodes = mapToTypeNodes((type).arguments, context); + return createTypeCall(fnNode, argNodes); + } Debug.fail("Should be unreachable."); @@ -3306,6 +3311,12 @@ namespace ts { writeType((type).indexType, TypeFormatFlags.None); writePunctuation(writer, SyntaxKind.CloseBracketToken); } + else if (type.flags & TypeFlags.TypeCall) { + writeType((type).function, TypeFormatFlags.None); + writePunctuation(writer, SyntaxKind.OpenParenToken); + writeTypeList((type).arguments, SyntaxKind.CommaToken); + writePunctuation(writer, SyntaxKind.CloseParenToken); + } else { // Should never get here // { ... } @@ -5912,10 +5923,18 @@ namespace ts { } } - function getConstraintOfType(type: TypeVariable | UnionOrIntersectionType): Type { + function getConstraintOfType(type: TypeVariable | UnionOrIntersectionType | TypeCallType): Type { return type.flags & TypeFlags.TypeParameter ? getConstraintOfTypeParameter(type) : type.flags & TypeFlags.IndexedAccess ? getConstraintOfIndexedAccess(type) : - getBaseConstraintOfType(type); + type.flags & TypeFlags.TypeCall ? getConstraintOfTypeCall(type) : + getBaseConstraintOfType(type); + } + + function getConstraintOfTypeCall(type: TypeCallType): Type { + const fn = type.function; + const args = map(type.arguments, getConstraintOfType); + const call = createTypeCallType(fn, args, type.node); + return getTypeFromTypeCall(call, type.node); } function getConstraintOfTypeParameter(typeParameter: TypeParameter): Type { @@ -7524,7 +7543,7 @@ namespace ts { } function getIndexType(type: Type): Type { - return maybeTypeOfKind(type, TypeFlags.TypeVariable) ? getIndexTypeForGenericType(type) : + return maybeTypeOfKind(type, TypeFlags.TypeVariable) || isGenericTypeCallType(type) ? getIndexTypeForGenericType(type) : getObjectFlags(type) & ObjectFlags.Mapped ? getConstraintTypeFromMappedType(type) : type.flags & TypeFlags.Any || getIndexInfoOfType(type, IndexKind.String) ? stringType : getLiteralTypeFromPropertyNames(type); @@ -7543,6 +7562,91 @@ namespace ts { return links.resolvedType; } + function isGenericTypeCallType(type: Type): boolean { + return type.flags & TypeFlags.TypeVariable ? true : + type.flags & TypeFlags.UnionOrIntersection ? forEach((type).types, isGenericTypeCallType) : + false; + } + + function createTypeCallType(fn: Type, args: Type[], node: TypeCallTypeNode): TypeCallType { + const type = createType(TypeFlags.TypeCall); + type.function = fn; + type.arguments = args; + type.node = node; + return type; + } + + function getTypeCallType(fn: Type, args: Type[], node: TypeCallTypeNode): Type { + const type = createTypeCallType(fn, args, node); + if (isGenericTypeCallType(fn) || some(args, isGenericTypeCallType)) { + return type; + } + return getTypeFromTypeCall(type, node); + } + + function getTypeFromTypeCall(type: TypeCallType, node: TypeCallTypeNode): Type { + const fn = type.function; + const args = type.arguments; + const candidates = getSignaturesOfType(fn, SignatureKind.Call); + const isSingleNonGenericCandidate = candidates.length === 1 && !candidates[0].typeParameters; + if (isSingleNonGenericCandidate) { + const sig = resolveCall(node, candidates, /*candidatesOutArray*/ [], /*fallBackError*/ undefined, args); + return sig ? getReturnTypeOfSignature(sig) : unknownType; + } + else { + // we have unions and they matter -- separately calculate the result for each permutation + const types: Type[] = []; + const indices: number[] = map(args, (tp: Type, i: number) => tp.flags & TypeFlags.Union && + some(candidates, (sig: Signature) => isGenericObjectType(getTypeAtPosition(sig, i))) ? + // ^ future consideration: argument/parameter i correspondence breaks down with tuple spreads + 0 : undefined); + const argTypes: Array = map(args, (tp: Type, i: number) => indices[i] !== undefined ? (tp).types : tp); + checkParams: while (true) { + const myArgs = map(argTypes, (tp: Type[] | Type, i: number) => { + const argIdx = indices[i]; + return argIdx === undefined ? tp : (tp)[argIdx]; + }); + const sig = resolveCall(node, candidates, /*candidatesOutArray*/ [], /*fallBackError*/ undefined, myArgs); + if (sig) { + types.push(getReturnTypeOfSignature(sig)); + } + // increment the next index to try the next permutation + for (let i = 0; i < indices.length; i++) { + const idx = indices[i]; + if (idx === undefined) { + // nothing to do here, try switching the next argument + continue; + } + else if (idx < (argTypes[i]).length - 1) { + // can increment without overflow + indices[i] = indices[i] + 1; + continue checkParams; + } + else { + // overflow, try switching the next argument as well + indices[i] = 0; + continue; + } + } + // all options tried, full overflow throughout for-loop, done + break; + } + return getUnionType(types); + } + } + + function getTypeFromTypeCallNode(node: TypeCallTypeNode): Type { + const links = getNodeLinks(node); + if (!links.resolvedType) { + links.resolvedType = getTypeCallType( + getTypeFromTypeNode(node.function), + map(node.arguments, getTypeFromTypeNode), + node + ); + } + return links.resolvedType; + } + function createIndexedAccessType(objectType: Type, indexType: Type) { const type = createType(TypeFlags.IndexedAccess); type.objectType = objectType; @@ -7736,7 +7840,7 @@ namespace ts { if (!links.resolvedType) { // Deferred resolution of members is handled by resolveObjectTypeMembers const aliasSymbol = getAliasSymbolForTypeNode(node); - if (node.symbol.members.size === 0 && !aliasSymbol) { + if (!node.symbol || node.symbol.members.size === 0 && !aliasSymbol) { links.resolvedType = emptyTypeLiteralType; } else { @@ -7753,7 +7857,7 @@ namespace ts { } function getAliasSymbolForTypeNode(node: TypeNode) { - return node.parent.kind === SyntaxKind.TypeAliasDeclaration ? getSymbolOfNode(node.parent) : undefined; + return node.parent && node.parent.kind === SyntaxKind.TypeAliasDeclaration ? getSymbolOfNode(node.parent) : undefined; } function getAliasTypeArgumentsForTypeNode(node: TypeNode) { @@ -7989,6 +8093,8 @@ namespace ts { return getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node); case SyntaxKind.TypeOperator: return getTypeFromTypeOperatorNode(node); + case SyntaxKind.TypeCall: + return getTypeFromTypeCallNode(node); case SyntaxKind.IndexedAccessType: return getTypeFromIndexedAccessTypeNode(node); case SyntaxKind.MappedType: @@ -8206,7 +8312,7 @@ namespace ts { } function isMappableType(type: Type) { - return type.flags & (TypeFlags.TypeParameter | TypeFlags.Object | TypeFlags.Intersection | TypeFlags.IndexedAccess); + return type.flags & (TypeFlags.TypeParameter | TypeFlags.Object | TypeFlags.Intersection | TypeFlags.IndexedAccess | TypeFlags.TypeCall); } function instantiateMappedObjectType(type: MappedType, mapper: TypeMapper): Type { @@ -8354,6 +8460,15 @@ namespace ts { if (type.flags & TypeFlags.IndexedAccess) { return getIndexedAccessType(instantiateType((type).objectType, mapper), instantiateType((type).indexType, mapper)); } + if (type.flags & TypeFlags.TypeCall) { + const typeCallNode = nodeBuilder.typeToTypeNode(type); + typeCallNode.parent = (type as TypeCallType).node; + return getTypeCallType( + instantiateType((type).function, mapper), + instantiateTypes((type).arguments, mapper), + typeCallNode + ); + } return type; } @@ -9308,6 +9423,15 @@ namespace ts { } } } + else if (target.flags & TypeFlags.TypeCall) { + const constraint = getConstraintOfTypeCall(target); + if (constraint) { + if (result = isRelatedTo(source, constraint, reportErrors)) { + errorInfo = saveErrorInfo; + return result; + } + } + } if (source.flags & TypeFlags.TypeParameter) { // A source type T is related to a target type { [P in keyof T]: X } if T[P] is related to X. @@ -9355,6 +9479,15 @@ namespace ts { } } } + else if (source.flags & TypeFlags.TypeCall) { + const constraint = getConstraintOfTypeCall(source); + if (constraint) { + if (result = isRelatedTo(source, constraint, reportErrors)) { + errorInfo = saveErrorInfo; + return result; + } + } + } else { if (getObjectFlags(source) & ObjectFlags.Reference && getObjectFlags(target) & ObjectFlags.Reference && (source).target === (target).target) { // We have type references to same target type, see if relationship holds for all type arguments @@ -13018,7 +13151,7 @@ namespace ts { // In a typed function call, an argument or substitution expression is contextually typed by the type of the corresponding parameter. function getContextualTypeForArgument(callTarget: CallLikeExpression, arg: Expression): Type { - const args = getEffectiveCallArguments(callTarget); + const args = >getEffectiveCallArguments(callTarget); const argIndex = indexOf(args, arg); if (argIndex >= 0) { // If we're already in the process of resolving the given signature, don't resolve again as @@ -13222,7 +13355,7 @@ namespace ts { return node.contextualType; } const parent = node.parent; - switch (parent.kind) { + switch (parent && parent.kind) { case SyntaxKind.VariableDeclaration: case SyntaxKind.Parameter: case SyntaxKind.PropertyDeclaration: @@ -15007,12 +15140,12 @@ namespace ts { return true; } - function callLikeExpressionMayHaveTypeArguments(node: CallLikeExpression): node is CallExpression | NewExpression { + function callLikeExpressionMayHaveTypeArguments(node: CallLike): node is CallExpression | NewExpression { // TODO: Also include tagged templates (https://github.com/Microsoft/TypeScript/issues/11947) return isCallOrNewExpression(node); } - function resolveUntypedCall(node: CallLikeExpression): Signature { + function resolveUntypedCall(node: CallLike): Signature { if (callLikeExpressionMayHaveTypeArguments(node)) { // Check type arguments even though we will give an error that untyped calls may not accept type arguments. // This gets us diagnostics for the type arguments and marks them as referenced. @@ -15030,7 +15163,7 @@ namespace ts { return anySignature; } - function resolveErrorCall(node: CallLikeExpression): Signature { + function resolveErrorCall(node: CallLike): Signature { resolveUntypedCall(node); return unknownSignature; } @@ -15089,7 +15222,7 @@ namespace ts { } } - function getSpreadArgumentIndex(args: ReadonlyArray): number { + function getSpreadArgumentIndex(args: Arguments): number { for (let i = 0; i < args.length; i++) { const arg = args[i]; if (arg && arg.kind === SyntaxKind.SpreadElement) { @@ -15099,7 +15232,7 @@ namespace ts { return -1; } - function hasCorrectArity(node: CallLikeExpression, args: ReadonlyArray, signature: Signature, signatureHelpTrailingComma = false) { + function hasCorrectArity(node: CallLike, args: Arguments, signature: Signature, signatureHelpTrailingComma = false) { let argCount: number; // Apparent number of arguments we will have in this call let typeArguments: NodeArray; // Type arguments (undefined if none) let callIsIncomplete: boolean; // In incomplete call we want to be lenient when we have too few arguments @@ -15163,7 +15296,7 @@ namespace ts { // the declared number of type parameters, the call has an incorrect arity. const numTypeParameters = length(signature.typeParameters); const minTypeArgumentCount = getMinTypeArgumentCount(signature.typeParameters); - const hasRightNumberOfTypeArgs = !typeArguments || + const hasRightNumberOfTypeArgs = !(typeArguments && typeArguments.length) || (typeArguments.length >= minTypeArgumentCount && typeArguments.length <= numTypeParameters); if (!hasRightNumberOfTypeArgs) { return false; @@ -15210,7 +15343,7 @@ namespace ts { return getSignatureInstantiation(signature, getInferredTypes(context)); } - function inferTypeArguments(node: CallLikeExpression, signature: Signature, args: ReadonlyArray, excludeArgument: boolean[], context: InferenceContext): Type[] { + function inferTypeArguments(node: CallLike, signature: Signature, args: Arguments, excludeArgument: boolean[], context: InferenceContext, argTypes?: Type[]): Type[] { // Clear out all the inference results from the last time inferTypeArguments was called on this context for (const inference of context.inferences) { // As an optimization, we don't have to clear (and later recompute) inferred types @@ -15226,7 +15359,7 @@ namespace ts { // example, given a 'function wrap(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 (node.kind !== SyntaxKind.Decorator) { + if (node.kind !== SyntaxKind.Decorator && node.kind !== SyntaxKind.TypeCall) { const contextualType = getContextualType(node); if (contextualType) { // We clone the contextual mapper to avoid disturbing a resolution in progress for an @@ -15263,17 +15396,17 @@ namespace ts { for (let i = 0; i < argCount; i++) { const arg = getEffectiveArgument(node, args, i); // If the effective argument is 'undefined', then it is an argument that is present but is synthetic. - if (arg === undefined || arg.kind !== SyntaxKind.OmittedExpression) { + if (isTypeCallTypeNode(node) || arg === undefined || arg.kind !== SyntaxKind.OmittedExpression) { const paramType = getTypeAtPosition(signature, i); - let argType = getEffectiveArgumentType(node, i); + let argType = argTypes ? argTypes[i] : getEffectiveArgumentType(node, i); // If the effective argument type is 'undefined', there is no synthetic type // for the argument. In that case, we should check the argument. - if (argType === undefined) { + if (!isTypeCallTypeNode(node) && 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 : context; - argType = checkExpressionWithContextualType(arg, paramType, mapper); + argType = checkExpressionWithContextualType(arg, paramType, mapper); } inferTypes(context.inferences, argType, paramType); @@ -15285,13 +15418,13 @@ namespace ts { // as we construct types for contextually typed parameters) // Decorators will not have `excludeArgument`, as their arguments cannot be contextually typed. // Tagged template expressions will always have `undefined` for `excludeArgument[0]`. - if (excludeArgument) { + if (!isTypeCallTypeNode(node) && excludeArgument) { for (let i = 0; i < argCount; i++) { // No need to check for omitted args and template expressions, their exclusion value is always undefined if (excludeArgument[i] === false) { const arg = args[i]; const paramType = getTypeAtPosition(signature, i); - inferTypes(context.inferences, checkExpressionWithContextualType(arg, paramType, context), paramType); + inferTypes(context.inferences, checkExpressionWithContextualType(arg, paramType, context), paramType); } } } @@ -15363,12 +15496,13 @@ namespace ts { } function checkApplicableSignature( - node: CallLikeExpression, - args: ReadonlyArray, + node: CallLike, + args: Arguments, signature: Signature, relation: Map, excludeArgument: boolean[], - reportErrors: boolean) { + reportErrors: boolean, + argTypes: Type[]) { if (isJsxOpeningLikeElement(node)) { return checkApplicableSignatureForJsxOpeningLikeElement(node, signature, relation); } @@ -15378,7 +15512,7 @@ namespace ts { // If the signature's 'this' type is voidType, then the check is skipped -- anything is compatible. // If the expression is a new expression, then the check is skipped. const thisArgumentNode = getThisArgumentOfCall(node); - const thisArgumentType = thisArgumentNode ? checkExpression(thisArgumentNode) : voidType; + const thisArgumentType = thisArgumentNode ? checkExpression(thisArgumentNode) : voidType; // type calls: TODO const errorNode = reportErrors ? (thisArgumentNode || node) : undefined; const headMessage = Diagnostics.The_this_context_of_type_0_is_not_assignable_to_method_s_this_of_type_1; if (!checkTypeRelatedTo(thisArgumentType, getThisTypeOfSignature(signature), relation, errorNode, headMessage)) { @@ -15388,14 +15522,14 @@ namespace ts { const headMessage = Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1; const argCount = getEffectiveArgumentCount(node, args, signature); for (let i = 0; i < argCount; i++) { - const arg = getEffectiveArgument(node, args, i); + const arg = getEffectiveArgument(node, args, i); // If the effective argument is 'undefined', then it is an argument that is present but is synthetic. - if (arg === undefined || arg.kind !== SyntaxKind.OmittedExpression) { + if (!isTypeCallTypeNode(node) && arg === undefined || arg.kind !== SyntaxKind.OmittedExpression) { // Check spread elements against rest type (from arity check we know spread argument corresponds to a rest parameter) const paramType = getTypeAtPosition(signature, i); // If the effective argument type is undefined, there is no synthetic type for the argument. // In that case, we should check the argument. - const argType = getEffectiveArgumentType(node, i) || + const argType = argTypes ? argTypes[i] : getEffectiveArgumentType(node, i) || checkExpressionWithContextualType(arg, paramType, excludeArgument && excludeArgument[i] ? identityMapper : undefined); // If one or more arguments are still excluded (as indicated by a non-null excludeArgument parameter), // we obtain the regular type of any object literal arguments because we may not have inferred complete @@ -15415,7 +15549,7 @@ namespace ts { /** * Returns the this argument in calls like x.f(...) and x[f](...). Undefined otherwise. */ - function getThisArgumentOfCall(node: CallLikeExpression): LeftHandSideExpression { + function getThisArgumentOfCall(node: CallLike): LeftHandSideExpression { if (node.kind === SyntaxKind.CallExpression) { const callee = (node).expression; if (callee.kind === SyntaxKind.PropertyAccessExpression) { @@ -15436,7 +15570,7 @@ namespace ts { * If 'node' is a Decorator, the argument list will be `undefined`, and its arguments and types * will be supplied from calls to `getEffectiveArgumentCount` and `getEffectiveArgumentType`. */ - function getEffectiveCallArguments(node: CallLikeExpression): ReadonlyArray { + function getEffectiveCallArguments(node: CallLike): Arguments { if (node.kind === SyntaxKind.TaggedTemplateExpression) { const template = (node).template; const args: Expression[] = [undefined]; @@ -15475,7 +15609,7 @@ namespace ts { * us to match a property decorator. * Otherwise, the argument count is the length of the 'args' array. */ - function getEffectiveArgumentCount(node: CallLikeExpression, args: ReadonlyArray, signature: Signature) { + function getEffectiveArgumentCount(node: CallLike, args: Arguments, signature: Signature) { if (node.kind === SyntaxKind.Decorator) { switch (node.parent.kind) { case SyntaxKind.ClassDeclaration: @@ -15688,7 +15822,7 @@ namespace ts { /** * Gets the effective argument type for an argument in a call expression. */ - function getEffectiveArgumentType(node: CallLikeExpression, argIndex: number): Type { + function getEffectiveArgumentType(node: CallLike, argIndex: number): Type { // Decorators provide special arguments, a tagged template expression provides // a special first argument, and string literals get string literal types // unless we're reporting errors @@ -15698,6 +15832,9 @@ namespace ts { else if (argIndex === 0 && node.kind === SyntaxKind.TaggedTemplateExpression) { return getGlobalTemplateStringsArrayType(); } + else if (node.kind === SyntaxKind.TypeCall) { + return getTypeFromTypeNode((node).arguments[argIndex]); + } // This is not a synthetic argument, so we return 'undefined' // to signal that the caller needs to check the argument. @@ -15707,7 +15844,7 @@ namespace ts { /** * Gets the effective argument expression for an argument in a call expression. */ - function getEffectiveArgument(node: CallLikeExpression, args: ReadonlyArray, argIndex: number) { + function getEffectiveArgument(node: CallLike, args: Arguments, argIndex: number) { // For a decorator or the first argument of a tagged template expression we return undefined. if (node.kind === SyntaxKind.Decorator || (argIndex === 0 && node.kind === SyntaxKind.TaggedTemplateExpression)) { @@ -15720,7 +15857,7 @@ namespace ts { /** * Gets the error node to use when reporting errors for an effective argument. */ - function getEffectiveArgumentErrorNode(node: CallLikeExpression, argIndex: number, arg: Expression) { + function getEffectiveArgumentErrorNode(node: CallLike, argIndex: number, arg: Expression) { if (node.kind === SyntaxKind.Decorator) { // For a decorator, we use the expression of the decorator for error reporting. return (node).expression; @@ -15730,11 +15867,11 @@ namespace ts { return (node).template; } else { - return arg; + return arg || node; } } - function resolveCall(node: CallLikeExpression, signatures: Signature[], candidatesOutArray: Signature[], fallbackError?: DiagnosticMessage): Signature { + function resolveCall(node: CallLike, signatures: Signature[], candidatesOutArray: Signature[], fallbackError?: DiagnosticMessage, argTypes?: Type[]): Signature { const isTaggedTemplate = node.kind === SyntaxKind.TaggedTemplateExpression; const isDecorator = node.kind === SyntaxKind.Decorator; const isJsxOpeningOrSelfClosingElement = isJsxOpeningLikeElement(node); @@ -15745,7 +15882,7 @@ namespace ts { typeArguments = (node).typeArguments; // We already perform checking on the type arguments on the class declaration itself. - if ((node).expression.kind !== SyntaxKind.SuperKeyword) { + if (!isTypeCallTypeNode(node) && (node).expression.kind !== SyntaxKind.SuperKeyword) { forEach(typeArguments, checkSourceElement); } } @@ -15777,11 +15914,11 @@ namespace ts { const isSingleNonGenericCandidate = candidates.length === 1 && !candidates[0].typeParameters; let excludeArgument: boolean[]; let excludeCount = 0; - if (!isDecorator && !isSingleNonGenericCandidate) { + if (!isDecorator && !isSingleNonGenericCandidate && !isTypeCallTypeNode(node)) { // We do not need to call `getEffectiveArgumentCount` here as it only // applies when calculating the number of arguments for a decorator. for (let i = isTaggedTemplate ? 1 : 0; i < args.length; i++) { - if (isContextSensitive(args[i])) { + if (isContextSensitive(args[i])) { if (!excludeArgument) { excludeArgument = new Array(args.length); } @@ -15855,7 +15992,7 @@ namespace ts { // in arguments too early. If possible, we'd like to only type them once we know the correct // overload. However, this matters for the case where the call is correct. When the call is // an error, we don't need to exclude any arguments, although it would cause no harm to do so. - checkApplicableSignature(node, args, candidateForArgumentError, assignableRelation, /*excludeArgument*/ undefined, /*reportErrors*/ true); + checkApplicableSignature(node, args, candidateForArgumentError, assignableRelation, /*excludeArgument*/ undefined, /*reportErrors*/ true, argTypes); } else if (candidateForTypeArgumentError) { const typeArguments = (node).typeArguments; @@ -15936,7 +16073,7 @@ namespace ts { if (!hasCorrectArity(node, args, candidate, signatureHelpTrailingComma)) { return undefined; } - if (!checkApplicableSignature(node, args, candidate, relation, excludeArgument, /*reportErrors*/ false)) { + if (!checkApplicableSignature(node, args, candidate, relation, excludeArgument, /*reportErrors*/ false, argTypes)) { candidateForArgumentError = candidate; return undefined; } @@ -15958,7 +16095,7 @@ namespace ts { candidate = originalCandidate; if (candidate.typeParameters) { let typeArgumentTypes: Type[]; - if (typeArguments) { + if (typeArguments && typeArguments.length) { typeArgumentTypes = fillMissingTypeArguments(map(typeArguments, getTypeFromTypeNode), candidate.typeParameters, getMinTypeArgumentCount(candidate.typeParameters)); if (!checkTypeArguments(candidate, typeArguments, typeArgumentTypes, /*reportErrors*/ false)) { candidateForTypeArgumentError = originalCandidate; @@ -15966,11 +16103,11 @@ namespace ts { } } else { - typeArgumentTypes = inferTypeArguments(node, candidate, args, excludeArgument, inferenceContext); + typeArgumentTypes = inferTypeArguments(node, candidate, args, excludeArgument, inferenceContext, argTypes); } candidate = getSignatureInstantiation(candidate, typeArgumentTypes); } - if (!checkApplicableSignature(node, args, candidate, relation, excludeArgument, /*reportErrors*/ false)) { + if (!checkApplicableSignature(node, args, candidate, relation, excludeArgument, /*reportErrors*/ false, argTypes)) { candidateForArgumentError = candidate; break; } @@ -18741,7 +18878,7 @@ namespace ts { for (let i = 0; i < typeParameters.length; i++) { const constraint = getConstraintOfTypeParameter(typeParameters[i]); if (constraint) { - if (!typeArguments) { + if (!(typeArguments && typeArguments.length)) { typeArguments = fillMissingTypeArguments(map(typeArgumentNodes, getTypeFromTypeNode), typeParameters, minTypeArgumentCount); mapper = createTypeMapper(typeParameters, typeArguments); } @@ -22433,6 +22570,8 @@ namespace ts { return checkBindingElement(node); case SyntaxKind.ClassDeclaration: return checkClassDeclaration(node); + case SyntaxKind.TypeCall: + return checkTypeCallNode(node); case SyntaxKind.InterfaceDeclaration: return checkInterfaceDeclaration(node); case SyntaxKind.TypeAliasDeclaration: @@ -22460,6 +22599,12 @@ namespace ts { } } + function checkTypeCallNode(node: TypeCallTypeNode) { + checkSourceElement(node.function); + forEach(node.arguments, checkSourceElement); + getTypeFromTypeCallNode(node); + } + // Function and class expression bodies are checked after all statements in the enclosing body. This is // to ensure constructs like the following are permitted: // const foo = function () { diff --git a/src/compiler/declarationEmitter.ts b/src/compiler/declarationEmitter.ts index 3de2091502949..fb86b39ac7684 100644 --- a/src/compiler/declarationEmitter.ts +++ b/src/compiler/declarationEmitter.ts @@ -445,6 +445,8 @@ namespace ts { return emitTypeOperator(type); case SyntaxKind.IndexedAccessType: return emitIndexedAccessType(type); + case SyntaxKind.TypeCall: + return emitTypeCall(type); case SyntaxKind.MappedType: return emitMappedType(type); case SyntaxKind.FunctionType: @@ -553,6 +555,13 @@ namespace ts { write("]"); } + function emitTypeCall(node: TypeCallTypeNode) { + emitType(node.function); + write("("); + emitCommaList(node.arguments, emitType); + write(")"); + } + function emitMappedType(node: MappedTypeNode) { const prevEnclosingDeclaration = enclosingDeclaration; enclosingDeclaration = node; diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 5444c618353bd..6f1ddb38a14e2 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -559,6 +559,8 @@ namespace ts { return emitMappedType(node); case SyntaxKind.LiteralType: return emitLiteralType(node); + case SyntaxKind.TypeCall: + return emitTypeCall(node); // Binding patterns case SyntaxKind.ObjectBindingPattern: @@ -1240,6 +1242,11 @@ namespace ts { write("]"); } + function emitTypeCall(node: TypeCallTypeNode) { + emit(node.function); + emitList(node, node.arguments, ListFormat.CallExpressionArguments); + } + function emitCallExpression(node: CallExpression) { emitExpression(node.expression); emitTypeArguments(node, node.typeArguments); diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 4492c3ed47426..dcc64f7029ad0 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -888,6 +888,20 @@ namespace ts { : node; } + export function createTypeCall(fn: TypeNode, argumentsArray: ReadonlyArray) { + const node = createSynthesizedNode(SyntaxKind.TypeCall); + node.function = parenthesizeElementTypeMember(fn); + node.arguments = parenthesizeElementTypeMembers(createNodeArray(argumentsArray)); + return node; + } + + export function updateTypeCall(node: TypeCallTypeNode, fn: TypeNode, argumentsArray: ReadonlyArray) { + return node.function !== fn + || node.arguments !== argumentsArray + ? updateNode(createTypeCall(fn, argumentsArray), node) + : node; + } + export function createCall(expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray) { const node = createSynthesizedNode(SyntaxKind.CallExpression); node.expression = parenthesizeForAccess(expression); diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 7486c7541bed4..fe7f8a9d47e90 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -170,6 +170,9 @@ namespace ts { case SyntaxKind.ElementAccessExpression: return visitNode(cbNode, (node).expression) || visitNode(cbNode, (node).argumentExpression); + case SyntaxKind.TypeCall: + return visitNode(cbNode, (node).function) || + visitNodes(cbNode, cbNodes, (node).arguments); case SyntaxKind.CallExpression: case SyntaxKind.NewExpression: return visitNode(cbNode, (node).expression) || @@ -2739,8 +2742,8 @@ namespace ts { return token() === SyntaxKind.CloseParenToken || isStartOfParameter() || isStartOfType(); } - function parseJSDocPostfixTypeOrHigher(): TypeNode { - const type = parseNonArrayType(); + function parseJSDocPostfixTypeOrHigher(typeNode?: TypeNode): TypeNode { + const type = typeNode || parseNonArrayType(); const kind = getKind(token()); if (!kind) return type; nextToken(); @@ -2762,8 +2765,8 @@ namespace ts { } } - function parseArrayTypeOrHigher(): TypeNode { - let type = parseJSDocPostfixTypeOrHigher(); + function parseArrayTypeOrHigher(typeNode?: TypeNode): TypeNode { + let type = parseJSDocPostfixTypeOrHigher(typeNode); while (!scanner.hasPrecedingLineBreak() && parseOptional(SyntaxKind.OpenBracketToken)) { if (isStartOfType()) { const node = createNode(SyntaxKind.IndexedAccessType, type.pos); @@ -2795,7 +2798,7 @@ namespace ts { case SyntaxKind.KeyOfKeyword: return parseTypeOperator(SyntaxKind.KeyOfKeyword); } - return parseArrayTypeOrHigher(); + return parseTypeCallRest(); } function parseUnionOrIntersectionType(kind: SyntaxKind.UnionType | SyntaxKind.IntersectionType, parseConstituentType: () => TypeNode, operator: SyntaxKind.BarToken | SyntaxKind.AmpersandToken): TypeNode { @@ -4241,6 +4244,53 @@ namespace ts { } } + // type equivalent of parseCallExpressionRest + function parseTypeCallRest(type?: TypeNode): TypeNode { + while (true) { + type = parseArrayTypeOrHigher(type); + // crap, the type may have parsed a semicolon... + if (!~[SyntaxKind.ThisType, SyntaxKind.ArrayType, SyntaxKind.TupleType, SyntaxKind.TypeOperator, SyntaxKind.LiteralType, SyntaxKind.NullKeyword, SyntaxKind.TrueKeyword, SyntaxKind.FalseKeyword, SyntaxKind.AnyKeyword, SyntaxKind.NumberKeyword, SyntaxKind.ObjectKeyword, SyntaxKind.BooleanKeyword, SyntaxKind.StringKeyword, SyntaxKind.SymbolKeyword, SyntaxKind.ThisKeyword, SyntaxKind.VoidKeyword, SyntaxKind.UndefinedKeyword, SyntaxKind.NullKeyword, SyntaxKind.NeverKeyword].indexOf(type.kind)) { + if (token() === SyntaxKind.OpenParenToken) { + const call = tryParse(() => parseTypeCall(type)); + if (call) { + type = call; + continue; + } + } + } + return type; + } + } + + function parseTypeCall(type: TypeNode) { + // if we're in what looks like a function declaration, scram + const arg = lookAhead(parseFirstParam); + if (arg && arg.type) { + return undefined; + } + + if (token() !== SyntaxKind.OpenParenToken) { + return; + } + const args = parseTypeArgumentList(); + const typeCall = createNode(SyntaxKind.TypeCall, type.pos); + typeCall.function = type; + typeCall.arguments = args; + return finishNode(typeCall); + } + + function parseFirstParam() { + parseExpected(SyntaxKind.OpenParenToken); + return parseParameter(); + } + + function parseTypeArgumentList() { + parseExpected(SyntaxKind.OpenParenToken); + const result = parseDelimitedList(ParsingContext.TypeArguments, parseType); + parseExpected(SyntaxKind.CloseParenToken); + return result; + } + function parseCallExpressionRest(expression: LeftHandSideExpression): LeftHandSideExpression { while (true) { expression = parseMemberExpressionRest(expression); diff --git a/src/compiler/symbolWalker.ts b/src/compiler/symbolWalker.ts index e20ef9f9d9877..b32977996f4ec 100644 --- a/src/compiler/symbolWalker.ts +++ b/src/compiler/symbolWalker.ts @@ -77,6 +77,9 @@ namespace ts { if (type.flags & TypeFlags.IndexedAccess) { visitIndexedAccessType(type as IndexedAccessType); } + if (type.flags & TypeFlags.TypeCall) { + visitTypeCallType(type as TypeCallType); + } } function visitTypeList(types: Type[]): void { @@ -111,6 +114,11 @@ namespace ts { visitType(type.constraint); } + function visitTypeCallType(type: TypeCallType): void { + visitType(type.function); + visitTypeList(type.arguments); + } + function visitMappedType(type: MappedType): void { visitType(type.typeParameter); visitType(type.constraintType); @@ -188,4 +196,4 @@ namespace ts { } } } -} \ No newline at end of file +} diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 692c758bc7504..8739ff56db90c 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -359,6 +359,7 @@ namespace ts { case SyntaxKind.IndexedAccessType: case SyntaxKind.MappedType: case SyntaxKind.LiteralType: + case SyntaxKind.TypeCall: // TypeScript type nodes are elided. case SyntaxKind.IndexSignature: @@ -1833,6 +1834,7 @@ namespace ts { case SyntaxKind.TypeQuery: case SyntaxKind.TypeOperator: case SyntaxKind.IndexedAccessType: + case SyntaxKind.TypeCall: case SyntaxKind.MappedType: case SyntaxKind.TypeLiteral: case SyntaxKind.AnyKeyword: diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 87ac4afbab145..bb33200b8f5a6 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -240,6 +240,7 @@ namespace ts { IndexedAccessType, MappedType, LiteralType, + TypeCall, // Binding patterns ObjectBindingPattern, ArrayBindingPattern, @@ -398,7 +399,7 @@ namespace ts { FirstFutureReservedWord = ImplementsKeyword, LastFutureReservedWord = YieldKeyword, FirstTypeNode = TypePredicate, - LastTypeNode = LiteralType, + LastTypeNode = TypeCall, FirstPunctuation = OpenBraceToken, LastPunctuation = CaretEqualsToken, FirstToken = Unknown, @@ -617,6 +618,8 @@ namespace ts { export type DeclarationName = Identifier | StringLiteral | NumericLiteral | ComputedPropertyName | BindingPattern; + export type Arguments = ReadonlyArray | ReadonlyArray; + export interface Declaration extends Node { _declarationBrand: any; } @@ -1495,6 +1498,12 @@ namespace ts { arguments: NodeArray; } + export interface TypeCallTypeNode extends TypeNode { + kind: SyntaxKind.TypeCall; + function: TypeNode; + arguments: NodeArray; + } + // see: https://tc39.github.io/ecma262/#prod-SuperCall export interface SuperCall extends CallExpression { expression: SuperExpression; @@ -1526,6 +1535,8 @@ namespace ts { export type CallLikeExpression = CallExpression | NewExpression | TaggedTemplateExpression | Decorator | JsxOpeningLikeElement; + export type CallLike = CallLikeExpression | TypeCallTypeNode; + export interface AsExpression extends Expression { kind: SyntaxKind.AsExpression; expression: Expression; @@ -3141,17 +3152,18 @@ namespace ts { Intersection = 1 << 17, // Intersection (T & U) Index = 1 << 18, // keyof T IndexedAccess = 1 << 19, // T[K] + TypeCall = 1 << 20, // F(T) /* @internal */ - FreshLiteral = 1 << 20, // Fresh literal type + FreshLiteral = 1 << 21, // Fresh literal type /* @internal */ - ContainsWideningType = 1 << 21, // Type is or contains undefined or null widening type + ContainsWideningType = 1 << 22, // Type is or contains undefined or null widening type /* @internal */ - ContainsObjectLiteral = 1 << 22, // Type is or contains object literal type + ContainsObjectLiteral = 1 << 23, // Type is or contains object literal type /* @internal */ - ContainsAnyFunctionType = 1 << 23, // Type is or contains the anyFunctionType - NonPrimitive = 1 << 24, // intrinsic object type + ContainsAnyFunctionType = 1 << 24, // Type is or contains the anyFunctionType + NonPrimitive = 1 << 25, // intrinsic object type /* @internal */ - JsxAttributes = 1 << 25, // Jsx attributes type + JsxAttributes = 1 << 26, // Jsx attributes type /* @internal */ Nullable = Undefined | Null, @@ -3170,12 +3182,12 @@ namespace ts { EnumLike = Enum | EnumLiteral, UnionOrIntersection = Union | Intersection, StructuredType = Object | Union | Intersection, - StructuredOrTypeVariable = StructuredType | TypeParameter | Index | IndexedAccess, - TypeVariable = TypeParameter | IndexedAccess, + StructuredOrTypeVariable = StructuredType | TypeParameter | Index | IndexedAccess | TypeCall, + TypeVariable = TypeParameter | IndexedAccess | TypeCall, // 'Narrowable' types are types where narrowing actually narrows. // This *should* be every type other than null, undefined, void, and never - Narrowable = Any | StructuredType | TypeParameter | Index | IndexedAccess | StringLike | NumberLike | BooleanLike | ESSymbol | NonPrimitive, + Narrowable = Any | StructuredType | TypeParameter | Index | IndexedAccess | TypeCall | StringLike | NumberLike | BooleanLike | ESSymbol | NonPrimitive, NotUnionOrUnit = Any | ESSymbol | Object | NonPrimitive, /* @internal */ RequiresWidening = ContainsWideningType | ContainsObjectLiteral, @@ -3400,6 +3412,13 @@ namespace ts { constraint?: Type; } + // F(T) types (TypeFlags.TypeCall) + export interface TypeCallType extends TypeVariable { + function: Type; + arguments: Type[]; + node: TypeCallTypeNode; + } + // keyof T types (TypeFlags.Index) export interface IndexType extends Type { type: TypeVariable | UnionOrIntersectionType; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index a32a82ecf1016..a69de01016095 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -306,6 +306,9 @@ namespace ts { if (nodeIsMissing(node)) { return ""; } + if (!sourceFile) { + sourceFile = getSourceFileOfNode(node); + } const text = sourceFile.text; return text.substring(includeTrivia ? node.pos : skipTrivia(text, node.pos), node.end); @@ -529,7 +532,12 @@ namespace ts { export function createDiagnosticForNode(node: Node, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number): Diagnostic { const sourceFile = getSourceFileOfNode(node); - return createDiagnosticForNodeInSourceFile(sourceFile, node, message, arg0, arg1, arg2); + if (!sourceFile || node.pos < 0) { + return createDiagnosticForNode(node.parent, message, arg0, arg1, arg2); + } + else { + return createDiagnosticForNodeInSourceFile(sourceFile, node, message, arg0, arg1, arg2); + } } export function createDiagnosticForNodeInSourceFile(sourceFile: SourceFile, node: Node, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number): Diagnostic { @@ -539,6 +547,7 @@ namespace ts { export function createDiagnosticForNodeFromMessageChain(node: Node, messageChain: DiagnosticMessageChain): Diagnostic { const sourceFile = getSourceFileOfNode(node); + if (!sourceFile) return createDiagnosticForNodeFromMessageChain(node.parent, messageChain); const span = getErrorSpanForNode(sourceFile, node); return { file: sourceFile, @@ -572,7 +581,13 @@ namespace ts { } export function getErrorSpanForNode(sourceFile: SourceFile, node: Node): TextSpan { + if (node && node.parent !== node && (!sourceFile || node.pos < 0)) { + return getErrorSpanForNode(sourceFile, node.parent); + } let errorNode = node; + if (node.pos < 0) { + return getErrorSpanForNode(sourceFile, node.parent); + } switch (node.kind) { case SyntaxKind.SourceFile: const pos = skipTrivia(sourceFile.text, 0, /*stopAfterLineBreak*/ false); @@ -4117,6 +4132,10 @@ namespace ts { return node.kind === SyntaxKind.IndexedAccessType; } + export function isTypeCallTypeNode(node: Node): node is TypeCallTypeNode { + return node.kind === SyntaxKind.TypeCall; + } + export function isMappedTypeNode(node: Node): node is MappedTypeNode { return node.kind === SyntaxKind.MappedType; } diff --git a/src/compiler/visitor.ts b/src/compiler/visitor.ts index 1ce42199372d8..ef581f307b743 100644 --- a/src/compiler/visitor.ts +++ b/src/compiler/visitor.ts @@ -446,6 +446,11 @@ namespace ts { visitNode((node).expression, visitor, isExpression), visitNode((node).argumentExpression, visitor, isExpression)); + case SyntaxKind.TypeCall: + return updateTypeCall(node, + visitNode((node).function, visitor, isTypeNode), + nodesVisitor((node).arguments, visitor, isTypeNode)); + case SyntaxKind.CallExpression: return updateCall(node, visitNode((node).expression, visitor, isExpression), @@ -1391,6 +1396,10 @@ namespace ts { result = reduceNode((node).expression, cbNode, result); break; + case SyntaxKind.TypeCall: + result = reduceNode((node).function, cbNode, result); + break; + // Enum case SyntaxKind.EnumMember: result = reduceNode((node).name, cbNode, result); diff --git a/tests/baselines/reference/arrayTypeOfTypeOf.symbols b/tests/baselines/reference/arrayTypeOfTypeOf.symbols new file mode 100644 index 0000000000000..9c63f3ac21af4 --- /dev/null +++ b/tests/baselines/reference/arrayTypeOfTypeOf.symbols @@ -0,0 +1,22 @@ +=== tests/cases/conformance/types/specifyingTypes/typeLiterals/arrayTypeOfTypeOf.ts === +// array type cannot use typeof. + +var x = 1; +>x : Symbol(x, Decl(arrayTypeOfTypeOf.ts, 2, 3)) + +var xs: typeof x[]; // Not an error. This is equivalent to Array +>xs : Symbol(xs, Decl(arrayTypeOfTypeOf.ts, 3, 3)) +>x : Symbol(x, Decl(arrayTypeOfTypeOf.ts, 2, 3)) + +var xs2: typeof Array; +>xs2 : Symbol(xs2, Decl(arrayTypeOfTypeOf.ts, 4, 3)) +>Array : Symbol(Array, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) + +var xs3: typeof Array; +>xs3 : Symbol(xs3, Decl(arrayTypeOfTypeOf.ts, 5, 3)) +>Array : Symbol(Array, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) + +var xs4: typeof Array; +>xs4 : Symbol(xs4, Decl(arrayTypeOfTypeOf.ts, 6, 3)) +>Array : Symbol(Array, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) + diff --git a/tests/baselines/reference/arrayTypeOfTypeOf.types b/tests/baselines/reference/arrayTypeOfTypeOf.types new file mode 100644 index 0000000000000..bb5856e5c7e40 --- /dev/null +++ b/tests/baselines/reference/arrayTypeOfTypeOf.types @@ -0,0 +1,23 @@ +=== tests/cases/conformance/types/specifyingTypes/typeLiterals/arrayTypeOfTypeOf.ts === +// array type cannot use typeof. + +var x = 1; +>x : number +>1 : 1 + +var xs: typeof x[]; // Not an error. This is equivalent to Array +>xs : number[] +>x : number + +var xs2: typeof Array; +>xs2 : ArrayConstructor +>Array : ArrayConstructor + +var xs3: typeof Array; +>xs3 : ArrayConstructor +>Array : ArrayConstructor + +var xs4: typeof Array; +>xs4 : ArrayConstructor +>Array : ArrayConstructor + diff --git a/tests/baselines/reference/contextualTypingWithGenericAndNonGenericSignature.js b/tests/baselines/reference/contextualTypingWithGenericAndNonGenericSignature.js index 5ee0c758022da..6358564384c72 100644 --- a/tests/baselines/reference/contextualTypingWithGenericAndNonGenericSignature.js +++ b/tests/baselines/reference/contextualTypingWithGenericAndNonGenericSignature.js @@ -2,7 +2,7 @@ //• If e is a FunctionExpression or ArrowFunctionExpression with no type parameters and no parameter or return type annotations, and T is a function type with EXACTLY ONE non - generic call signature, then any inferences made for type parameters referenced by the parameters of T’s call signature are fixed(section 4.12.2) and e is processed with the contextual type T, as described in section 4.9.3. var f2: { - (x: string, y: number): string; + (x: string, y: number): string (x: T, y: U): T }; diff --git a/tests/baselines/reference/contextualTypingWithGenericAndNonGenericSignature.symbols b/tests/baselines/reference/contextualTypingWithGenericAndNonGenericSignature.symbols index d7ba6f0ddc376..7f9b6e3fb52d8 100644 --- a/tests/baselines/reference/contextualTypingWithGenericAndNonGenericSignature.symbols +++ b/tests/baselines/reference/contextualTypingWithGenericAndNonGenericSignature.symbols @@ -4,7 +4,7 @@ var f2: { >f2 : Symbol(f2, Decl(contextualTypingWithGenericAndNonGenericSignature.ts, 2, 3)) - (x: string, y: number): string; + (x: string, y: number): string >x : Symbol(x, Decl(contextualTypingWithGenericAndNonGenericSignature.ts, 3, 5)) >y : Symbol(y, Decl(contextualTypingWithGenericAndNonGenericSignature.ts, 3, 15)) diff --git a/tests/baselines/reference/contextualTypingWithGenericAndNonGenericSignature.types b/tests/baselines/reference/contextualTypingWithGenericAndNonGenericSignature.types index ca6c5b35f3d0e..b7b66aecdb853 100644 --- a/tests/baselines/reference/contextualTypingWithGenericAndNonGenericSignature.types +++ b/tests/baselines/reference/contextualTypingWithGenericAndNonGenericSignature.types @@ -4,7 +4,7 @@ var f2: { >f2 : { (x: string, y: number): string; (x: T, y: U): T; } - (x: string, y: number): string; + (x: string, y: number): string >x : string >y : number diff --git a/tests/baselines/reference/emptyTypeArgumentList.errors.txt b/tests/baselines/reference/emptyTypeArgumentList.errors.txt index 036f307447b83..74fbe4d328ecc 100644 --- a/tests/baselines/reference/emptyTypeArgumentList.errors.txt +++ b/tests/baselines/reference/emptyTypeArgumentList.errors.txt @@ -1,11 +1,8 @@ -tests/cases/compiler/emptyTypeArgumentList.ts(2,1): error TS2558: Expected 1 type arguments, but got 0. tests/cases/compiler/emptyTypeArgumentList.ts(2,4): error TS1099: Type argument list cannot be empty. -==== tests/cases/compiler/emptyTypeArgumentList.ts (2 errors) ==== +==== tests/cases/compiler/emptyTypeArgumentList.ts (1 errors) ==== function foo() { } foo<>(); - ~~~~~~~ -!!! error TS2558: Expected 1 type arguments, but got 0. ~~ !!! error TS1099: Type argument list cannot be empty. \ No newline at end of file diff --git a/tests/baselines/reference/emptyTypeArgumentList.symbols b/tests/baselines/reference/emptyTypeArgumentList.symbols new file mode 100644 index 0000000000000..efbe5705f4fe8 --- /dev/null +++ b/tests/baselines/reference/emptyTypeArgumentList.symbols @@ -0,0 +1,8 @@ +=== tests/cases/compiler/emptyTypeArgumentList.ts === +function foo() { } +>foo : Symbol(foo, Decl(emptyTypeArgumentList.ts, 0, 0)) +>T : Symbol(T, Decl(emptyTypeArgumentList.ts, 0, 13)) + +foo<>(); +>foo : Symbol(foo, Decl(emptyTypeArgumentList.ts, 0, 0)) + diff --git a/tests/baselines/reference/emptyTypeArgumentList.types b/tests/baselines/reference/emptyTypeArgumentList.types new file mode 100644 index 0000000000000..bfc11caa3661b --- /dev/null +++ b/tests/baselines/reference/emptyTypeArgumentList.types @@ -0,0 +1,9 @@ +=== tests/cases/compiler/emptyTypeArgumentList.ts === +function foo() { } +>foo : () => void +>T : T + +foo<>(); +>foo<>() : void +>foo : () => void + diff --git a/tests/baselines/reference/emptyTypeArgumentListWithNew.errors.txt b/tests/baselines/reference/emptyTypeArgumentListWithNew.errors.txt index 648aa7c6c5085..22f196e6e49ef 100644 --- a/tests/baselines/reference/emptyTypeArgumentListWithNew.errors.txt +++ b/tests/baselines/reference/emptyTypeArgumentListWithNew.errors.txt @@ -1,11 +1,8 @@ -tests/cases/compiler/emptyTypeArgumentListWithNew.ts(2,1): error TS2558: Expected 1 type arguments, but got 0. tests/cases/compiler/emptyTypeArgumentListWithNew.ts(2,8): error TS1099: Type argument list cannot be empty. -==== tests/cases/compiler/emptyTypeArgumentListWithNew.ts (2 errors) ==== +==== tests/cases/compiler/emptyTypeArgumentListWithNew.ts (1 errors) ==== class foo { } new foo<>(); - ~~~~~~~~~~~ -!!! error TS2558: Expected 1 type arguments, but got 0. ~~ !!! error TS1099: Type argument list cannot be empty. \ No newline at end of file diff --git a/tests/baselines/reference/emptyTypeArgumentListWithNew.symbols b/tests/baselines/reference/emptyTypeArgumentListWithNew.symbols new file mode 100644 index 0000000000000..34ce38aa47816 --- /dev/null +++ b/tests/baselines/reference/emptyTypeArgumentListWithNew.symbols @@ -0,0 +1,8 @@ +=== tests/cases/compiler/emptyTypeArgumentListWithNew.ts === +class foo { } +>foo : Symbol(foo, Decl(emptyTypeArgumentListWithNew.ts, 0, 0)) +>T : Symbol(T, Decl(emptyTypeArgumentListWithNew.ts, 0, 10)) + +new foo<>(); +>foo : Symbol(foo, Decl(emptyTypeArgumentListWithNew.ts, 0, 0)) + diff --git a/tests/baselines/reference/emptyTypeArgumentListWithNew.types b/tests/baselines/reference/emptyTypeArgumentListWithNew.types new file mode 100644 index 0000000000000..310b5f7cd142c --- /dev/null +++ b/tests/baselines/reference/emptyTypeArgumentListWithNew.types @@ -0,0 +1,9 @@ +=== tests/cases/compiler/emptyTypeArgumentListWithNew.ts === +class foo { } +>foo : foo +>T : T + +new foo<>(); +>new foo<>() : foo<{}> +>foo : typeof foo + diff --git a/tests/baselines/reference/invalidTypeOfTarget.errors.txt b/tests/baselines/reference/invalidTypeOfTarget.errors.txt index e658ab68c81bf..84a5b5adbd4eb 100644 --- a/tests/baselines/reference/invalidTypeOfTarget.errors.txt +++ b/tests/baselines/reference/invalidTypeOfTarget.errors.txt @@ -1,6 +1,9 @@ tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(1,16): error TS1003: Identifier expected. +tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(2,9): error TS2346: Call target does not contain any signatures. tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(2,16): error TS1003: Identifier expected. -tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(2,24): error TS1005: '=>' expected. +tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(2,18): error TS1005: ',' expected. +tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(2,20): error TS1134: Variable declaration expected. +tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(2,24): error TS1109: Expression expected. tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(3,16): error TS1003: Identifier expected. tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(4,16): error TS1003: Identifier expected. tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(5,16): error TS1003: Identifier expected. @@ -12,15 +15,21 @@ tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts(8,16): error TS1003: Identifier expected. -==== tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts (12 errors) ==== +==== tests/cases/conformance/types/specifyingTypes/typeQueries/invalidTypeOfTarget.ts (15 errors) ==== var x1: typeof {}; ~ !!! error TS1003: Identifier expected. var x2: typeof (): void; + ~~~~~~~~~ +!!! error TS2346: Call target does not contain any signatures. ~ !!! error TS1003: Identifier expected. + ~ +!!! error TS1005: ',' expected. + ~~~~ +!!! error TS1134: Variable declaration expected. ~ -!!! error TS1005: '=>' expected. +!!! error TS1109: Expression expected. var x3: typeof 1; ~ !!! error TS1003: Identifier expected. diff --git a/tests/baselines/reference/invalidTypeOfTarget.js b/tests/baselines/reference/invalidTypeOfTarget.js index ebc5bb708757c..cda6f90a2f319 100644 --- a/tests/baselines/reference/invalidTypeOfTarget.js +++ b/tests/baselines/reference/invalidTypeOfTarget.js @@ -10,7 +10,8 @@ var x8: typeof /123/; //// [invalidTypeOfTarget.js] var x1 = {}; -var x2 = function () { return ; }; +var x2; +void ; var x3 = 1; var x4 = ''; var x5; diff --git a/tests/baselines/reference/objectRestNegative.errors.txt b/tests/baselines/reference/objectRestNegative.errors.txt index ced36a642d605..e919be4f19c68 100644 --- a/tests/baselines/reference/objectRestNegative.errors.txt +++ b/tests/baselines/reference/objectRestNegative.errors.txt @@ -39,7 +39,7 @@ tests/cases/conformance/types/rest/objectRestNegative.ts(17,9): error TS2701: Th return rest; } - let rest: { b: string } + let rest: { b: string }; ({a, ...rest.b + rest.b} = o); ~~~~~~~~~~~~~~~ !!! error TS2701: The target of an object rest assignment must be a variable or a property access. diff --git a/tests/baselines/reference/objectRestNegative.js b/tests/baselines/reference/objectRestNegative.js index 915e0a0e86732..3b02895a5c48d 100644 --- a/tests/baselines/reference/objectRestNegative.js +++ b/tests/baselines/reference/objectRestNegative.js @@ -14,7 +14,7 @@ function generic(t: T) { return rest; } -let rest: { b: string } +let rest: { b: string }; ({a, ...rest.b + rest.b} = o); diff --git a/tests/baselines/reference/overloadSelection.js b/tests/baselines/reference/overloadSelection.js new file mode 100644 index 0000000000000..dbaf6bf61f2da --- /dev/null +++ b/tests/baselines/reference/overloadSelection.js @@ -0,0 +1,10 @@ +//// [overloadSelection.ts] +interface Match { + (o: object): 0; + (o: any): 1; +} +type Wrap = (v: T) => Match(T); +type A = Wrap(RegExp); + + +//// [overloadSelection.js] diff --git a/tests/baselines/reference/overloadSelection.symbols b/tests/baselines/reference/overloadSelection.symbols new file mode 100644 index 0000000000000..913010f4de8f6 --- /dev/null +++ b/tests/baselines/reference/overloadSelection.symbols @@ -0,0 +1,23 @@ +=== tests/cases/compiler/overloadSelection.ts === +interface Match { +>Match : Symbol(Match, Decl(overloadSelection.ts, 0, 0)) + + (o: object): 0; +>o : Symbol(o, Decl(overloadSelection.ts, 1, 3)) + + (o: any): 1; +>o : Symbol(o, Decl(overloadSelection.ts, 2, 3)) +} +type Wrap = (v: T) => Match(T); +>Wrap : Symbol(Wrap, Decl(overloadSelection.ts, 3, 1)) +>T : Symbol(T, Decl(overloadSelection.ts, 4, 13)) +>v : Symbol(v, Decl(overloadSelection.ts, 4, 16)) +>T : Symbol(T, Decl(overloadSelection.ts, 4, 13)) +>Match : Symbol(Match, Decl(overloadSelection.ts, 0, 0)) +>T : Symbol(T, Decl(overloadSelection.ts, 4, 13)) + +type A = Wrap(RegExp); +>A : Symbol(A, Decl(overloadSelection.ts, 4, 34)) +>Wrap : Symbol(Wrap, Decl(overloadSelection.ts, 3, 1)) +>RegExp : Symbol(RegExp, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) + diff --git a/tests/baselines/reference/overloadSelection.types b/tests/baselines/reference/overloadSelection.types new file mode 100644 index 0000000000000..3084fa5e9fabe --- /dev/null +++ b/tests/baselines/reference/overloadSelection.types @@ -0,0 +1,23 @@ +=== tests/cases/compiler/overloadSelection.ts === +interface Match { +>Match : Match + + (o: object): 0; +>o : object + + (o: any): 1; +>o : any +} +type Wrap = (v: T) => Match(T); +>Wrap : Wrap +>T : T +>v : T +>T : T +>Match : Match +>T : T + +type A = Wrap(RegExp); +>A : 0 +>Wrap : Wrap +>RegExp : RegExp + diff --git a/tests/baselines/reference/typeAliasDeclarationEmit.symbols b/tests/baselines/reference/typeAliasDeclarationEmit.symbols index 5f98ea75a5a26..631264fdc8281 100644 --- a/tests/baselines/reference/typeAliasDeclarationEmit.symbols +++ b/tests/baselines/reference/typeAliasDeclarationEmit.symbols @@ -1,13 +1,12 @@ === tests/cases/compiler/typeAliasDeclarationEmit.ts === - export type callback = () => T; >callback : Symbol(callback, Decl(typeAliasDeclarationEmit.ts, 0, 0)) ->T : Symbol(T, Decl(typeAliasDeclarationEmit.ts, 1, 21)) ->T : Symbol(T, Decl(typeAliasDeclarationEmit.ts, 1, 21)) +>T : Symbol(T, Decl(typeAliasDeclarationEmit.ts, 0, 21)) +>T : Symbol(T, Decl(typeAliasDeclarationEmit.ts, 0, 21)) export type CallbackArray = () => T; ->CallbackArray : Symbol(CallbackArray, Decl(typeAliasDeclarationEmit.ts, 1, 34)) ->T : Symbol(T, Decl(typeAliasDeclarationEmit.ts, 3, 26)) +>CallbackArray : Symbol(CallbackArray, Decl(typeAliasDeclarationEmit.ts, 0, 34)) +>T : Symbol(T, Decl(typeAliasDeclarationEmit.ts, 2, 26)) >callback : Symbol(callback, Decl(typeAliasDeclarationEmit.ts, 0, 0)) ->T : Symbol(T, Decl(typeAliasDeclarationEmit.ts, 3, 26)) +>T : Symbol(T, Decl(typeAliasDeclarationEmit.ts, 2, 26)) diff --git a/tests/baselines/reference/typeAliasDeclarationEmit.types b/tests/baselines/reference/typeAliasDeclarationEmit.types index cc7d5f9a3422e..b1b338a0a467d 100644 --- a/tests/baselines/reference/typeAliasDeclarationEmit.types +++ b/tests/baselines/reference/typeAliasDeclarationEmit.types @@ -1,5 +1,4 @@ === tests/cases/compiler/typeAliasDeclarationEmit.ts === - export type callback = () => T; >callback : callback >T : T diff --git a/tests/baselines/reference/typeCall.js b/tests/baselines/reference/typeCall.js new file mode 100644 index 0000000000000..aad62ab573620 --- /dev/null +++ b/tests/baselines/reference/typeCall.js @@ -0,0 +1,325 @@ +//// [typeCall.ts] +type F1 = () => 1; +type a = F1(); + +type F2 = (a: string) => 1; +type b = F2('foo'); + +interface F3 { + (): 1; + (a: number): 2; + (a: string): 3; +} +type c = F3(); +type d = F3(123); +type e = F3('foo'); + +declare function f4(a: string): 1; +let a = 'foo'; +type f = typeof f4(typeof a); + +type g = (() => 1)(); + +type Id = (v: T) => T; +type h = Id(123); + +type Wrap = Id(T); +type i = Wrap<123>; + +type F5 = () => () => { a: () => 1; }; +type j = F5()()['a'](); + +interface IsPrimitive { + (o: object): '0'; + (o: any): '1'; +} +type stringIsPrimitive = IsPrimitive(string); +type regexpIsPrimitive = IsPrimitive(RegExp); + +// alternative, pass as parameters +type genericIsPrimitive3 = (v: T) => IsPrimitive(T); +type stringIsPrimitive3 = genericIsPrimitive3(string); +type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) + +declare function angularFactory R, R extends (foo: T) => T[]>(g: G): R(123); +angularFactory((...args: any[]) => (foo: T) => [foo] as [T]) + +interface BoolToString { + (v: false & true): never; + (v: false): 'false'; + (v: true): 'true'; + (v: boolean): 'true' | 'false'; +} +type strTrue = BoolToString(true); +type strFalse = BoolToString(false); +type strEither = BoolToString(true | false); +type strBool = BoolToString(boolean); +type strAny = BoolToString(any); // fails, want the fallback, but yields 'false' + +// declare function safeDivide< +// B extends number, +// NotZero = ((v: '1') => 'whatever')({ +// (v: 0): '0'; +// (v: number): '1'; +// }(B)) +// >(a: number, b: B): number; +// // Argument of type '"0"' is not assignable to parameter of type '"1"' +// safeDivide(3, 1); +// safeDivide(3, 0); // should error + +type map = any, O extends { [k: string]: T }, T>(fn: Fn, obj: O) => { [P in keyof O]: Fn(O[P]) }; +type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); +declare function map(v: T) => any, O extends { [k: string]: T }, T>(fn: Fn, obj: O): { [P in keyof O]: Fn(O[P]) }; +let z = map((v: T) => [v] as [T], { a: 1, b: 2, c: 3 } as { a: 1, b: 2, c: 3 }); + +type Inc = { [k: string]: string; 0:'1', 1:'2', 2:'3', 3:'4', 4:'5', 5:'6', 6:'7', 7:'8', 8:'9' }; +type StringToNumber = { [k: string]: number; 0:0,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8}; +type TupleHasIndex = ({[K in keyof Arr]: '1' } & { [k: string]: '0' })[I]; +type PathFn, I extends string = '0'> = + { 1: PathFn, 0: T }[TupleHasIndex]; +type PathTest = PathFn<{ a: { b: ['c', { d: 'e' }] } }, ['a', 'b', '1', 'd']>; +declare function path>(obj: T, path: R): PathFn; +const obj = null! as { a: { b: ['c', { d: 'e' }] } }; +const keys = null! as ['a', 'b', '1', 'd']; +const pathTest = path(obj, keys); +// "e" + +// type Reduce< +// Fn extends (previousValue: T, currentValue: R[number], currentIndex?: number, array?: R) => any, +// T, +// R extends any[], +// I extends string = '0' +// > = { 1: Reduce, 0: T }[TupleHasIndex]; +// // fails with error: Cannot read property 'flags' of undefined +// declare function reduce< +// Fn extends (previousValue: any, currentValue: R[number], currentIndex?: number, array?: R) => any, +// R extends any[], +// U, +// I extends string = '0' +// >(callbackfn: Fn, initialValue: U, array: R): Reduce; +// declare function path2>(obj: T, path: R): +// Reduce<(previousValue: Prev, currentValue: Curr, currentIndex?: number, array?: any[]) => Prev[Curr], T, R>; +// const pathTest2 = path2(obj, keys); +// // "e" + +// binary function composition +type Fn1 = (v1: T1[]) => { [k: string]: T1 }; +type Fn2 = (v2: { [k: string]: T2 }) => ReadonlyArray; +let fn1 = null! as Fn1; +let fn2 = null! as Fn2; +type Fn3 = (v3: T3) => Fn2(Fn1(T3)); +declare function fn3 T, Fun2 extends (v: T) => any, P1, T>(fun1: Fun1, fun2: Fun2): (...args: any[] /* todo: specify*/) => Fn2(Fn1(P1)); +let ones = null! as 1[]; +type Fn4b = Fn3(typeof ones); +type Fn4c = Fn3(1[]); +let y = fn2(fn1(ones)); +type Y = Fn2(Fn1(1[])); +// let z2 = fn3(fn1, fn2)(ones); // Cannot read property 'parent' of undefined + +interface isT { + (v: never): '0'; + (v: T): '1'; + (v: any): '0'; +} +type Matches = isT(V); +type isBool = isT; +let falseBool: isBool(false); // 1 +let trueBool: isBool(true); // 1 +let strBool: isBool(string); // 0 +let anyBool: isBool(any); // 0 +let neverBool: isBool(never); // 0 + +type Assert = { + (v: null | undefined): never; + (v: U): U; +}(T); +let assert: Assert; // string + +type Minus = { + (v: B): never; + (v: U): U; +}(A); +let noNumbers: Minus; // string + +interface UnwrapPromise { + (v: PromiseLike): UnwrapPromise(U); + (v: U): U; +}; +declare const testUnwrap1: UnwrapPromise(string); +declare const testUnwrap2: UnwrapPromise(Promise); +declare const testUnwrap3: UnwrapPromise(boolean | Promise); +declare function myThen( + prom: Promise, + onfulfilled?: ((value: T) => TResult1) | undefined | null, + onrejected?: ((reason: any) => TResult2) | undefined | null + ): Promise; +declare const pr: Promise; +declare function f(x: number): Promise; +declare function g(x: number): number | Promise; +const testThen = myThen(pr, f, g); + +interface Promise { + then( + onfulfilled?: ((value: T) => TResult1) | undefined | null, + onrejected?: ((reason: any) => TResult2) | undefined | null + ): Promise; +} +// prevents error: Argument of type '(x: number) => number | Promise' is not assignable to parameter of type '(value: number) => string | PromiseLike'; +const tryProm = pr.then((x: number) => { + if (x < 0) return f(x); + return x; +}); + +interface ObjectHasStringIndex { + // (o: T): T[string]; + (o: { [k: string]: any }): '1'; + (o: {}): '0'; +} +let ObjectHasStringIndexTestT: ObjectHasStringIndex({ [k: string]: 123 }); // '1' +let ObjectHasStringIndexTestF: ObjectHasStringIndex({ a: 123 }); // wanted '0', got '1'... so can't match for index, and erroring RHS yields `any`. ouch. + +type IndexCall { [k: string]: any }, K extends keyof (T())> = T()[K]; +type CallMember any }, K extends keyof T> = T[K](); +type MappedMemberCall any }> = { [K in keyof T]: T[K]() }; + +type HasKey = ( + { [K in keyof T]: 'true' } & + { [key: string]: 'false' } +)[Key]; + +type HasKindKey any> = HasKey; +type MapHasKey any }, Key extends string> = { + [K in keyof T]: HasKey +}; + +type KeyOfCall any> = keyof (T()); + +type Strip1 any> = { [K in keyof (T())]: T()[K] }; +type Strip2 { [k: string]: () => any }> = { [K in keyof (T())]: T()[K]() }; + +type Obj = { + x: () => number, + z: () => { kind: 'Just', value: string } +} + +type T1 = (() => number)(); +type T7 = CallMember; +type T8 = IndexCall<() => Obj, 'x'>; +type T9 = MappedMemberCall; // fails, unresolved, want { x: number, z: { kind: 'Just', value: string } } +type T13 = keyof (() => Obj)(); +type T14 = KeyOfCall<() => Obj>; +type T15 = Obj['z']()['kind']; +type T16 = MapHasKey; // fails, unresolved, want { x: 'false', z: 'true' } +type T17 = Strip1<() => Obj>; // fails, unresolved, want { x: () => number, z: () => { kind: 'Just', value: string } } +type T19 = Strip2<() => Obj>; // fails, unresolved, want { x: number, z: { kind: 'Just', value: string } } + +let a1: () => string; +let b1: typeof a1(); +type Abc any> = T(); +let c1: Abc; + +declare function infer1 any>(x: T): T(); +infer1(null! as () => number); + +declare function infer2 any>(x: { a: T }): T(); +infer2(null! as { a: () => number }); + +declare function infer3(x: { a: () => T }): T; +infer3(null! as { a: () => number }); +const res3: number = infer3(null! as { a: () => number }); + +declare function infer4(x: T, y: () => T): void; +infer4(5, () => 5); + +function assignability(x: T, y: () => T) { + const a: T = x; + const b: T = y(); +} + +// function mappedAssignability(x: T, y: CallMember) { +// const d: T() = y; +// } + +// function mappedComparability(x: T, y: CallMember) { +// x === x; +// y === y; +// x === y; +// } + +// type IdMapped = { [K in keyof T]: T[K] } + +// function mappedRelations(x: IdMapped, y: Partial, z: CallMember) { +// x === z; +// y === z; + +// const a: IdMapped = z; +// const b: Partial = z; +// } + +// mappedRelations(null! as Obj, null! as Partial, null! as CallMember); +// mappedRelations(null! as CallMember, null! as CallMember, null! as CallMember); + + +//// [typeCall.js] +var a = 'foo'; +angularFactory(function () { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + return function (foo) { return [foo]; }; +}); +var z = map(function (v) { return [v]; }, { a: 1, b: 2, c: 3 }); +var obj = null; +var keys = null; +var pathTest = path(obj, keys); +var fn1 = null; +var fn2 = null; +var ones = null; +var y = fn2(fn1(ones)); +var falseBool; // 1 +var trueBool; // 1 +var strBool; // 0 +var anyBool; // 0 +var neverBool; // 0 +var assert; // string +var noNumbers; // string +; +var testThen = myThen(pr, f, g); +// prevents error: Argument of type '(x: number) => number | Promise' is not assignable to parameter of type '(value: number) => string | PromiseLike'; +var tryProm = pr.then(function (x) { + if (x < 0) + return f(x); + return x; +}); +var ObjectHasStringIndexTestT; // '1' +var ObjectHasStringIndexTestF; // wanted '0', got '1'... so can't match for index, and erroring RHS yields `any`. ouch. +var a1; +var b1; +var c1; +infer1(null); +infer2(null); +infer3(null); +var res3 = infer3(null); +infer4(5, function () { return 5; }); +function assignability(x, y) { + var a = x; + var b = y(); +} +// function mappedAssignability(x: T, y: CallMember) { +// const d: T() = y; +// } +// function mappedComparability(x: T, y: CallMember) { +// x === x; +// y === y; +// x === y; +// } +// type IdMapped = { [K in keyof T]: T[K] } +// function mappedRelations(x: IdMapped, y: Partial, z: CallMember) { +// x === z; +// y === z; +// const a: IdMapped = z; +// const b: Partial = z; +// } +// mappedRelations(null! as Obj, null! as Partial, null! as CallMember); +// mappedRelations(null! as CallMember, null! as CallMember, null! as CallMember); diff --git a/tests/baselines/reference/typeCall.symbols b/tests/baselines/reference/typeCall.symbols new file mode 100644 index 0000000000000..d329978856f7d --- /dev/null +++ b/tests/baselines/reference/typeCall.symbols @@ -0,0 +1,918 @@ +=== tests/cases/compiler/typeCall.ts === +type F1 = () => 1; +>F1 : Symbol(F1, Decl(typeCall.ts, 0, 0)) + +type a = F1(); +>a : Symbol(a, Decl(typeCall.ts, 0, 18), Decl(typeCall.ts, 16, 3)) +>F1 : Symbol(F1, Decl(typeCall.ts, 0, 0)) + +type F2 = (a: string) => 1; +>F2 : Symbol(F2, Decl(typeCall.ts, 1, 14)) +>a : Symbol(a, Decl(typeCall.ts, 3, 11)) + +type b = F2('foo'); +>b : Symbol(b, Decl(typeCall.ts, 3, 27)) +>F2 : Symbol(F2, Decl(typeCall.ts, 1, 14)) + +interface F3 { +>F3 : Symbol(F3, Decl(typeCall.ts, 4, 19)) + + (): 1; + (a: number): 2; +>a : Symbol(a, Decl(typeCall.ts, 8, 5)) + + (a: string): 3; +>a : Symbol(a, Decl(typeCall.ts, 9, 5)) +} +type c = F3(); +>c : Symbol(c, Decl(typeCall.ts, 10, 1)) +>F3 : Symbol(F3, Decl(typeCall.ts, 4, 19)) + +type d = F3(123); +>d : Symbol(d, Decl(typeCall.ts, 11, 14)) +>F3 : Symbol(F3, Decl(typeCall.ts, 4, 19)) + +type e = F3('foo'); +>e : Symbol(e, Decl(typeCall.ts, 12, 17)) +>F3 : Symbol(F3, Decl(typeCall.ts, 4, 19)) + +declare function f4(a: string): 1; +>f4 : Symbol(f4, Decl(typeCall.ts, 13, 19)) +>a : Symbol(a, Decl(typeCall.ts, 15, 20)) + +let a = 'foo'; +>a : Symbol(a, Decl(typeCall.ts, 0, 18), Decl(typeCall.ts, 16, 3)) + +type f = typeof f4(typeof a); +>f : Symbol(f, Decl(typeCall.ts, 16, 14), Decl(typeCall.ts, 154, 34)) +>f4 : Symbol(f4, Decl(typeCall.ts, 13, 19)) +>a : Symbol(a, Decl(typeCall.ts, 0, 18), Decl(typeCall.ts, 16, 3)) + +type g = (() => 1)(); +>g : Symbol(g, Decl(typeCall.ts, 17, 29), Decl(typeCall.ts, 155, 47)) + +type Id = (v: T) => T; +>Id : Symbol(Id, Decl(typeCall.ts, 19, 21)) +>T : Symbol(T, Decl(typeCall.ts, 21, 11)) +>v : Symbol(v, Decl(typeCall.ts, 21, 14)) +>T : Symbol(T, Decl(typeCall.ts, 21, 11)) +>T : Symbol(T, Decl(typeCall.ts, 21, 11)) + +type h = Id(123); +>h : Symbol(h, Decl(typeCall.ts, 21, 25)) +>Id : Symbol(Id, Decl(typeCall.ts, 19, 21)) + +type Wrap = Id(T); +>Wrap : Symbol(Wrap, Decl(typeCall.ts, 22, 17)) +>T : Symbol(T, Decl(typeCall.ts, 24, 10)) +>Id : Symbol(Id, Decl(typeCall.ts, 19, 21)) +>T : Symbol(T, Decl(typeCall.ts, 24, 10)) + +type i = Wrap<123>; +>i : Symbol(i, Decl(typeCall.ts, 24, 21)) +>Wrap : Symbol(Wrap, Decl(typeCall.ts, 22, 17)) + +type F5 = () => () => { a: () => 1; }; +>F5 : Symbol(F5, Decl(typeCall.ts, 25, 19)) +>a : Symbol(a, Decl(typeCall.ts, 27, 23)) + +type j = F5()()['a'](); +>j : Symbol(j, Decl(typeCall.ts, 27, 38)) +>F5 : Symbol(F5, Decl(typeCall.ts, 25, 19)) + +interface IsPrimitive { +>IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 28, 23)) + + (o: object): '0'; +>o : Symbol(o, Decl(typeCall.ts, 31, 3)) + + (o: any): '1'; +>o : Symbol(o, Decl(typeCall.ts, 32, 3)) +} +type stringIsPrimitive = IsPrimitive(string); +>stringIsPrimitive : Symbol(stringIsPrimitive, Decl(typeCall.ts, 33, 1)) +>IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 28, 23)) + +type regexpIsPrimitive = IsPrimitive(RegExp); +>regexpIsPrimitive : Symbol(regexpIsPrimitive, Decl(typeCall.ts, 34, 45)) +>IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 28, 23)) +>RegExp : Symbol(RegExp, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) + +// alternative, pass as parameters +type genericIsPrimitive3 = (v: T) => IsPrimitive(T); +>genericIsPrimitive3 : Symbol(genericIsPrimitive3, Decl(typeCall.ts, 35, 45)) +>T : Symbol(T, Decl(typeCall.ts, 38, 28)) +>v : Symbol(v, Decl(typeCall.ts, 38, 31)) +>T : Symbol(T, Decl(typeCall.ts, 38, 28)) +>IsPrimitive : Symbol(IsPrimitive, Decl(typeCall.ts, 28, 23)) +>T : Symbol(T, Decl(typeCall.ts, 38, 28)) + +type stringIsPrimitive3 = genericIsPrimitive3(string); +>stringIsPrimitive3 : Symbol(stringIsPrimitive3, Decl(typeCall.ts, 38, 55)) +>genericIsPrimitive3 : Symbol(genericIsPrimitive3, Decl(typeCall.ts, 35, 45)) + +type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) +>regexpIsPrimitive3 : Symbol(regexpIsPrimitive3, Decl(typeCall.ts, 39, 54)) +>genericIsPrimitive3 : Symbol(genericIsPrimitive3, Decl(typeCall.ts, 35, 45)) +>RegExp : Symbol(RegExp, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) + +declare function angularFactory R, R extends (foo: T) => T[]>(g: G): R(123); +>angularFactory : Symbol(angularFactory, Decl(typeCall.ts, 40, 53)) +>G : Symbol(G, Decl(typeCall.ts, 42, 32)) +>args : Symbol(args, Decl(typeCall.ts, 42, 43)) +>R : Symbol(R, Decl(typeCall.ts, 42, 64)) +>R : Symbol(R, Decl(typeCall.ts, 42, 64)) +>T : Symbol(T, Decl(typeCall.ts, 42, 76)) +>foo : Symbol(foo, Decl(typeCall.ts, 42, 79)) +>T : Symbol(T, Decl(typeCall.ts, 42, 76)) +>T : Symbol(T, Decl(typeCall.ts, 42, 76)) +>g : Symbol(g, Decl(typeCall.ts, 42, 95)) +>G : Symbol(G, Decl(typeCall.ts, 42, 32)) +>R : Symbol(R, Decl(typeCall.ts, 42, 64)) + +angularFactory((...args: any[]) => (foo: T) => [foo] as [T]) +>angularFactory : Symbol(angularFactory, Decl(typeCall.ts, 40, 53)) +>args : Symbol(args, Decl(typeCall.ts, 43, 16)) +>T : Symbol(T, Decl(typeCall.ts, 43, 36)) +>foo : Symbol(foo, Decl(typeCall.ts, 43, 39)) +>T : Symbol(T, Decl(typeCall.ts, 43, 36)) +>foo : Symbol(foo, Decl(typeCall.ts, 43, 39)) +>T : Symbol(T, Decl(typeCall.ts, 43, 36)) + +interface BoolToString { +>BoolToString : Symbol(BoolToString, Decl(typeCall.ts, 43, 63)) + + (v: false & true): never; +>v : Symbol(v, Decl(typeCall.ts, 46, 5)) + + (v: false): 'false'; +>v : Symbol(v, Decl(typeCall.ts, 47, 5)) + + (v: true): 'true'; +>v : Symbol(v, Decl(typeCall.ts, 48, 5)) + + (v: boolean): 'true' | 'false'; +>v : Symbol(v, Decl(typeCall.ts, 49, 5)) +} +type strTrue = BoolToString(true); +>strTrue : Symbol(strTrue, Decl(typeCall.ts, 50, 1)) +>BoolToString : Symbol(BoolToString, Decl(typeCall.ts, 43, 63)) + +type strFalse = BoolToString(false); +>strFalse : Symbol(strFalse, Decl(typeCall.ts, 51, 34)) +>BoolToString : Symbol(BoolToString, Decl(typeCall.ts, 43, 63)) + +type strEither = BoolToString(true | false); +>strEither : Symbol(strEither, Decl(typeCall.ts, 52, 36)) +>BoolToString : Symbol(BoolToString, Decl(typeCall.ts, 43, 63)) + +type strBool = BoolToString(boolean); +>strBool : Symbol(strBool, Decl(typeCall.ts, 53, 44), Decl(typeCall.ts, 126, 3)) +>BoolToString : Symbol(BoolToString, Decl(typeCall.ts, 43, 63)) + +type strAny = BoolToString(any); // fails, want the fallback, but yields 'false' +>strAny : Symbol(strAny, Decl(typeCall.ts, 54, 37)) +>BoolToString : Symbol(BoolToString, Decl(typeCall.ts, 43, 63)) + +// declare function safeDivide< +// B extends number, +// NotZero = ((v: '1') => 'whatever')({ +// (v: 0): '0'; +// (v: number): '1'; +// }(B)) +// >(a: number, b: B): number; +// // Argument of type '"0"' is not assignable to parameter of type '"1"' +// safeDivide(3, 1); +// safeDivide(3, 0); // should error + +type map = any, O extends { [k: string]: T }, T>(fn: Fn, obj: O) => { [P in keyof O]: Fn(O[P]) }; +>map : Symbol(map, Decl(typeCall.ts, 55, 32), Decl(typeCall.ts, 69, 53)) +>Fn : Symbol(Fn, Decl(typeCall.ts, 68, 12)) +>v : Symbol(v, Decl(typeCall.ts, 68, 24)) +>T : Symbol(T, Decl(typeCall.ts, 68, 67)) +>O : Symbol(O, Decl(typeCall.ts, 68, 37)) +>k : Symbol(k, Decl(typeCall.ts, 68, 51)) +>T : Symbol(T, Decl(typeCall.ts, 68, 67)) +>T : Symbol(T, Decl(typeCall.ts, 68, 67)) +>fn : Symbol(fn, Decl(typeCall.ts, 68, 71)) +>Fn : Symbol(Fn, Decl(typeCall.ts, 68, 12)) +>obj : Symbol(obj, Decl(typeCall.ts, 68, 78)) +>O : Symbol(O, Decl(typeCall.ts, 68, 37)) +>P : Symbol(P, Decl(typeCall.ts, 68, 93)) +>O : Symbol(O, Decl(typeCall.ts, 68, 37)) +>Fn : Symbol(Fn, Decl(typeCall.ts, 68, 12)) +>O : Symbol(O, Decl(typeCall.ts, 68, 37)) +>P : Symbol(P, Decl(typeCall.ts, 68, 93)) + +type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); +>z : Symbol(z, Decl(typeCall.ts, 68, 119), Decl(typeCall.ts, 71, 3)) +>map : Symbol(map, Decl(typeCall.ts, 55, 32), Decl(typeCall.ts, 69, 53)) +>T : Symbol(T, Decl(typeCall.ts, 69, 14)) +>v : Symbol(v, Decl(typeCall.ts, 69, 17)) +>T : Symbol(T, Decl(typeCall.ts, 69, 14)) +>T : Symbol(T, Decl(typeCall.ts, 69, 14)) +>a : Symbol(a, Decl(typeCall.ts, 69, 32)) +>b : Symbol(b, Decl(typeCall.ts, 69, 38)) +>c : Symbol(c, Decl(typeCall.ts, 69, 44)) + +declare function map(v: T) => any, O extends { [k: string]: T }, T>(fn: Fn, obj: O): { [P in keyof O]: Fn(O[P]) }; +>map : Symbol(map, Decl(typeCall.ts, 55, 32), Decl(typeCall.ts, 69, 53)) +>Fn : Symbol(Fn, Decl(typeCall.ts, 70, 21)) +>T : Symbol(T, Decl(typeCall.ts, 70, 33)) +>v : Symbol(v, Decl(typeCall.ts, 70, 36)) +>T : Symbol(T, Decl(typeCall.ts, 70, 33)) +>O : Symbol(O, Decl(typeCall.ts, 70, 49)) +>k : Symbol(k, Decl(typeCall.ts, 70, 63)) +>T : Symbol(T, Decl(typeCall.ts, 70, 79)) +>T : Symbol(T, Decl(typeCall.ts, 70, 79)) +>fn : Symbol(fn, Decl(typeCall.ts, 70, 83)) +>Fn : Symbol(Fn, Decl(typeCall.ts, 70, 21)) +>obj : Symbol(obj, Decl(typeCall.ts, 70, 90)) +>O : Symbol(O, Decl(typeCall.ts, 70, 49)) +>P : Symbol(P, Decl(typeCall.ts, 70, 103)) +>O : Symbol(O, Decl(typeCall.ts, 70, 49)) +>Fn : Symbol(Fn, Decl(typeCall.ts, 70, 21)) +>O : Symbol(O, Decl(typeCall.ts, 70, 49)) +>P : Symbol(P, Decl(typeCall.ts, 70, 103)) + +let z = map((v: T) => [v] as [T], { a: 1, b: 2, c: 3 } as { a: 1, b: 2, c: 3 }); +>z : Symbol(z, Decl(typeCall.ts, 68, 119), Decl(typeCall.ts, 71, 3)) +>map : Symbol(map, Decl(typeCall.ts, 55, 32), Decl(typeCall.ts, 69, 53)) +>T : Symbol(T, Decl(typeCall.ts, 71, 13)) +>v : Symbol(v, Decl(typeCall.ts, 71, 16)) +>T : Symbol(T, Decl(typeCall.ts, 71, 13)) +>v : Symbol(v, Decl(typeCall.ts, 71, 16)) +>T : Symbol(T, Decl(typeCall.ts, 71, 13)) +>a : Symbol(a, Decl(typeCall.ts, 71, 38)) +>b : Symbol(b, Decl(typeCall.ts, 71, 44)) +>c : Symbol(c, Decl(typeCall.ts, 71, 50)) +>a : Symbol(a, Decl(typeCall.ts, 71, 62)) +>b : Symbol(b, Decl(typeCall.ts, 71, 68)) +>c : Symbol(c, Decl(typeCall.ts, 71, 74)) + +type Inc = { [k: string]: string; 0:'1', 1:'2', 2:'3', 3:'4', 4:'5', 5:'6', 6:'7', 7:'8', 8:'9' }; +>Inc : Symbol(Inc, Decl(typeCall.ts, 71, 83)) +>k : Symbol(k, Decl(typeCall.ts, 73, 14)) + +type StringToNumber = { [k: string]: number; 0:0,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8}; +>StringToNumber : Symbol(StringToNumber, Decl(typeCall.ts, 73, 98)) +>k : Symbol(k, Decl(typeCall.ts, 74, 25)) + +type TupleHasIndex = ({[K in keyof Arr]: '1' } & { [k: string]: '0' })[I]; +>TupleHasIndex : Symbol(TupleHasIndex, Decl(typeCall.ts, 74, 82)) +>Arr : Symbol(Arr, Decl(typeCall.ts, 75, 19)) +>I : Symbol(I, Decl(typeCall.ts, 75, 37)) +>K : Symbol(K, Decl(typeCall.ts, 75, 61)) +>Arr : Symbol(Arr, Decl(typeCall.ts, 75, 19)) +>k : Symbol(k, Decl(typeCall.ts, 75, 89)) +>I : Symbol(I, Decl(typeCall.ts, 75, 37)) + +type PathFn, I extends string = '0'> = +>PathFn : Symbol(PathFn, Decl(typeCall.ts, 75, 111)) +>T : Symbol(T, Decl(typeCall.ts, 76, 12)) +>k : Symbol(k, Decl(typeCall.ts, 76, 25)) +>R : Symbol(R, Decl(typeCall.ts, 76, 43)) +>Array : Symbol(Array, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>I : Symbol(I, Decl(typeCall.ts, 76, 68)) + + { 1: PathFn, 0: T }[TupleHasIndex]; +>PathFn : Symbol(PathFn, Decl(typeCall.ts, 75, 111)) +>T : Symbol(T, Decl(typeCall.ts, 76, 12)) +>R : Symbol(R, Decl(typeCall.ts, 76, 43)) +>StringToNumber : Symbol(StringToNumber, Decl(typeCall.ts, 73, 98)) +>I : Symbol(I, Decl(typeCall.ts, 76, 68)) +>R : Symbol(R, Decl(typeCall.ts, 76, 43)) +>Inc : Symbol(Inc, Decl(typeCall.ts, 71, 83)) +>I : Symbol(I, Decl(typeCall.ts, 76, 68)) +>T : Symbol(T, Decl(typeCall.ts, 76, 12)) +>TupleHasIndex : Symbol(TupleHasIndex, Decl(typeCall.ts, 74, 82)) +>R : Symbol(R, Decl(typeCall.ts, 76, 43)) +>I : Symbol(I, Decl(typeCall.ts, 76, 68)) + +type PathTest = PathFn<{ a: { b: ['c', { d: 'e' }] } }, ['a', 'b', '1', 'd']>; +>PathTest : Symbol(PathTest, Decl(typeCall.ts, 77, 81)) +>PathFn : Symbol(PathFn, Decl(typeCall.ts, 75, 111)) +>a : Symbol(a, Decl(typeCall.ts, 78, 24)) +>b : Symbol(b, Decl(typeCall.ts, 78, 29)) +>d : Symbol(d, Decl(typeCall.ts, 78, 40)) + +declare function path>(obj: T, path: R): PathFn; +>path : Symbol(path, Decl(typeCall.ts, 78, 78)) +>T : Symbol(T, Decl(typeCall.ts, 79, 22)) +>k : Symbol(k, Decl(typeCall.ts, 79, 35)) +>R : Symbol(R, Decl(typeCall.ts, 79, 53)) +>Array : Symbol(Array, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>obj : Symbol(obj, Decl(typeCall.ts, 79, 79)) +>T : Symbol(T, Decl(typeCall.ts, 79, 22)) +>path : Symbol(path, Decl(typeCall.ts, 79, 86)) +>R : Symbol(R, Decl(typeCall.ts, 79, 53)) +>PathFn : Symbol(PathFn, Decl(typeCall.ts, 75, 111)) +>T : Symbol(T, Decl(typeCall.ts, 79, 22)) +>R : Symbol(R, Decl(typeCall.ts, 79, 53)) + +const obj = null! as { a: { b: ['c', { d: 'e' }] } }; +>obj : Symbol(obj, Decl(typeCall.ts, 80, 5)) +>a : Symbol(a, Decl(typeCall.ts, 80, 22)) +>b : Symbol(b, Decl(typeCall.ts, 80, 27)) +>d : Symbol(d, Decl(typeCall.ts, 80, 38)) + +const keys = null! as ['a', 'b', '1', 'd']; +>keys : Symbol(keys, Decl(typeCall.ts, 81, 5)) + +const pathTest = path(obj, keys); +>pathTest : Symbol(pathTest, Decl(typeCall.ts, 82, 5)) +>path : Symbol(path, Decl(typeCall.ts, 78, 78)) +>obj : Symbol(obj, Decl(typeCall.ts, 80, 5)) +>keys : Symbol(keys, Decl(typeCall.ts, 81, 5)) + +// "e" + +// type Reduce< +// Fn extends (previousValue: T, currentValue: R[number], currentIndex?: number, array?: R) => any, +// T, +// R extends any[], +// I extends string = '0' +// > = { 1: Reduce, 0: T }[TupleHasIndex]; +// // fails with error: Cannot read property 'flags' of undefined +// declare function reduce< +// Fn extends (previousValue: any, currentValue: R[number], currentIndex?: number, array?: R) => any, +// R extends any[], +// U, +// I extends string = '0' +// >(callbackfn: Fn, initialValue: U, array: R): Reduce; +// declare function path2>(obj: T, path: R): +// Reduce<(previousValue: Prev, currentValue: Curr, currentIndex?: number, array?: any[]) => Prev[Curr], T, R>; +// const pathTest2 = path2(obj, keys); +// // "e" + +// binary function composition +type Fn1 = (v1: T1[]) => { [k: string]: T1 }; +>Fn1 : Symbol(Fn1, Decl(typeCall.ts, 82, 33)) +>T1 : Symbol(T1, Decl(typeCall.ts, 104, 12)) +>v1 : Symbol(v1, Decl(typeCall.ts, 104, 31)) +>T1 : Symbol(T1, Decl(typeCall.ts, 104, 12)) +>k : Symbol(k, Decl(typeCall.ts, 104, 47)) +>T1 : Symbol(T1, Decl(typeCall.ts, 104, 12)) + +type Fn2 = (v2: { [k: string]: T2 }) => ReadonlyArray; +>Fn2 : Symbol(Fn2, Decl(typeCall.ts, 104, 64)) +>T2 : Symbol(T2, Decl(typeCall.ts, 105, 12)) +>v2 : Symbol(v2, Decl(typeCall.ts, 105, 16)) +>k : Symbol(k, Decl(typeCall.ts, 105, 23)) +>T2 : Symbol(T2, Decl(typeCall.ts, 105, 12)) +>ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.d.ts, --, --)) +>T2 : Symbol(T2, Decl(typeCall.ts, 105, 12)) + +let fn1 = null! as Fn1; +>fn1 : Symbol(fn1, Decl(typeCall.ts, 106, 3)) +>Fn1 : Symbol(Fn1, Decl(typeCall.ts, 82, 33)) + +let fn2 = null! as Fn2; +>fn2 : Symbol(fn2, Decl(typeCall.ts, 107, 3)) +>Fn2 : Symbol(Fn2, Decl(typeCall.ts, 104, 64)) + +type Fn3 = (v3: T3) => Fn2(Fn1(T3)); +>Fn3 : Symbol(Fn3, Decl(typeCall.ts, 107, 23)) +>T3 : Symbol(T3, Decl(typeCall.ts, 108, 12)) +>v3 : Symbol(v3, Decl(typeCall.ts, 108, 33)) +>T3 : Symbol(T3, Decl(typeCall.ts, 108, 12)) +>Fn2 : Symbol(Fn2, Decl(typeCall.ts, 104, 64)) +>Fn1 : Symbol(Fn1, Decl(typeCall.ts, 82, 33)) +>T3 : Symbol(T3, Decl(typeCall.ts, 108, 12)) + +declare function fn3 T, Fun2 extends (v: T) => any, P1, T>(fun1: Fun1, fun2: Fun2): (...args: any[] /* todo: specify*/) => Fn2(Fn1(P1)); +>fn3 : Symbol(fn3, Decl(typeCall.ts, 108, 57)) +>Fun1 : Symbol(Fun1, Decl(typeCall.ts, 109, 21)) +>p1 : Symbol(p1, Decl(typeCall.ts, 109, 35)) +>P1 : Symbol(P1, Decl(typeCall.ts, 109, 95)) +>T : Symbol(T, Decl(typeCall.ts, 109, 99)) +>Fun2 : Symbol(Fun2, Decl(typeCall.ts, 109, 67)) +>v : Symbol(v, Decl(typeCall.ts, 109, 82)) +>T : Symbol(T, Decl(typeCall.ts, 109, 99)) +>P1 : Symbol(P1, Decl(typeCall.ts, 109, 95)) +>T : Symbol(T, Decl(typeCall.ts, 109, 99)) +>fun1 : Symbol(fun1, Decl(typeCall.ts, 109, 103)) +>Fun1 : Symbol(Fun1, Decl(typeCall.ts, 109, 21)) +>fun2 : Symbol(fun2, Decl(typeCall.ts, 109, 114)) +>Fun2 : Symbol(Fun2, Decl(typeCall.ts, 109, 67)) +>args : Symbol(args, Decl(typeCall.ts, 109, 129)) +>Fn2 : Symbol(Fn2, Decl(typeCall.ts, 104, 64)) +>Fn1 : Symbol(Fn1, Decl(typeCall.ts, 82, 33)) +>P1 : Symbol(P1, Decl(typeCall.ts, 109, 95)) + +let ones = null! as 1[]; +>ones : Symbol(ones, Decl(typeCall.ts, 110, 3)) + +type Fn4b = Fn3(typeof ones); +>Fn4b : Symbol(Fn4b, Decl(typeCall.ts, 110, 24)) +>Fn3 : Symbol(Fn3, Decl(typeCall.ts, 107, 23)) +>ones : Symbol(ones, Decl(typeCall.ts, 110, 3)) + +type Fn4c = Fn3(1[]); +>Fn4c : Symbol(Fn4c, Decl(typeCall.ts, 111, 29)) +>Fn3 : Symbol(Fn3, Decl(typeCall.ts, 107, 23)) + +let y = fn2(fn1(ones)); +>y : Symbol(y, Decl(typeCall.ts, 113, 3)) +>fn2 : Symbol(fn2, Decl(typeCall.ts, 107, 3)) +>fn1 : Symbol(fn1, Decl(typeCall.ts, 106, 3)) +>ones : Symbol(ones, Decl(typeCall.ts, 110, 3)) + +type Y = Fn2(Fn1(1[])); +>Y : Symbol(Y, Decl(typeCall.ts, 113, 23)) +>Fn2 : Symbol(Fn2, Decl(typeCall.ts, 104, 64)) +>Fn1 : Symbol(Fn1, Decl(typeCall.ts, 82, 33)) + +// let z2 = fn3(fn1, fn2)(ones); // Cannot read property 'parent' of undefined + +interface isT { +>isT : Symbol(isT, Decl(typeCall.ts, 114, 23)) +>T : Symbol(T, Decl(typeCall.ts, 117, 14)) + + (v: never): '0'; +>v : Symbol(v, Decl(typeCall.ts, 118, 3)) + + (v: T): '1'; +>v : Symbol(v, Decl(typeCall.ts, 119, 3)) +>T : Symbol(T, Decl(typeCall.ts, 117, 14)) + + (v: any): '0'; +>v : Symbol(v, Decl(typeCall.ts, 120, 3)) +} +type Matches = isT(V); +>Matches : Symbol(Matches, Decl(typeCall.ts, 121, 1)) +>V : Symbol(V, Decl(typeCall.ts, 122, 13)) +>T : Symbol(T, Decl(typeCall.ts, 122, 15)) +>isT : Symbol(isT, Decl(typeCall.ts, 114, 23)) +>T : Symbol(T, Decl(typeCall.ts, 122, 15)) +>V : Symbol(V, Decl(typeCall.ts, 122, 13)) + +type isBool = isT; +>isBool : Symbol(isBool, Decl(typeCall.ts, 122, 31)) +>isT : Symbol(isT, Decl(typeCall.ts, 114, 23)) + +let falseBool: isBool(false); // 1 +>falseBool : Symbol(falseBool, Decl(typeCall.ts, 124, 3)) +>isBool : Symbol(isBool, Decl(typeCall.ts, 122, 31)) + +let trueBool: isBool(true); // 1 +>trueBool : Symbol(trueBool, Decl(typeCall.ts, 125, 3)) +>isBool : Symbol(isBool, Decl(typeCall.ts, 122, 31)) + +let strBool: isBool(string); // 0 +>strBool : Symbol(strBool, Decl(typeCall.ts, 53, 44), Decl(typeCall.ts, 126, 3)) +>isBool : Symbol(isBool, Decl(typeCall.ts, 122, 31)) + +let anyBool: isBool(any); // 0 +>anyBool : Symbol(anyBool, Decl(typeCall.ts, 127, 3)) +>isBool : Symbol(isBool, Decl(typeCall.ts, 122, 31)) + +let neverBool: isBool(never); // 0 +>neverBool : Symbol(neverBool, Decl(typeCall.ts, 128, 3)) +>isBool : Symbol(isBool, Decl(typeCall.ts, 122, 31)) + +type Assert = { +>Assert : Symbol(Assert, Decl(typeCall.ts, 128, 29)) +>T : Symbol(T, Decl(typeCall.ts, 130, 12)) + + (v: null | undefined): never; +>v : Symbol(v, Decl(typeCall.ts, 131, 3)) + + (v: U): U; +>U : Symbol(U, Decl(typeCall.ts, 132, 3)) +>v : Symbol(v, Decl(typeCall.ts, 132, 6)) +>U : Symbol(U, Decl(typeCall.ts, 132, 3)) +>U : Symbol(U, Decl(typeCall.ts, 132, 3)) + +}(T); +>T : Symbol(T, Decl(typeCall.ts, 130, 12)) + +let assert: Assert; // string +>assert : Symbol(assert, Decl(typeCall.ts, 134, 3)) +>Assert : Symbol(Assert, Decl(typeCall.ts, 128, 29)) + +type Minus = { +>Minus : Symbol(Minus, Decl(typeCall.ts, 134, 39)) +>A : Symbol(A, Decl(typeCall.ts, 136, 11)) +>B : Symbol(B, Decl(typeCall.ts, 136, 13)) + + (v: B): never; +>v : Symbol(v, Decl(typeCall.ts, 137, 3)) +>B : Symbol(B, Decl(typeCall.ts, 136, 13)) + + (v: U): U; +>U : Symbol(U, Decl(typeCall.ts, 138, 3)) +>v : Symbol(v, Decl(typeCall.ts, 138, 6)) +>U : Symbol(U, Decl(typeCall.ts, 138, 3)) +>U : Symbol(U, Decl(typeCall.ts, 138, 3)) + +}(A); +>A : Symbol(A, Decl(typeCall.ts, 136, 11)) + +let noNumbers: Minus; // string +>noNumbers : Symbol(noNumbers, Decl(typeCall.ts, 140, 3)) +>Minus : Symbol(Minus, Decl(typeCall.ts, 134, 39)) + +interface UnwrapPromise { +>UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 140, 46)) + + (v: PromiseLike): UnwrapPromise(U); +>U : Symbol(U, Decl(typeCall.ts, 143, 3)) +>v : Symbol(v, Decl(typeCall.ts, 143, 6)) +>PromiseLike : Symbol(PromiseLike, Decl(lib.d.ts, --, --)) +>U : Symbol(U, Decl(typeCall.ts, 143, 3)) +>UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 140, 46)) +>U : Symbol(U, Decl(typeCall.ts, 143, 3)) + + (v: U): U; +>U : Symbol(U, Decl(typeCall.ts, 144, 3)) +>v : Symbol(v, Decl(typeCall.ts, 144, 6)) +>U : Symbol(U, Decl(typeCall.ts, 144, 3)) +>U : Symbol(U, Decl(typeCall.ts, 144, 3)) + +}; +declare const testUnwrap1: UnwrapPromise(string); +>testUnwrap1 : Symbol(testUnwrap1, Decl(typeCall.ts, 146, 13)) +>UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 140, 46)) + +declare const testUnwrap2: UnwrapPromise(Promise); +>testUnwrap2 : Symbol(testUnwrap2, Decl(typeCall.ts, 147, 13)) +>UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 140, 46)) +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 157, 34)) + +declare const testUnwrap3: UnwrapPromise(boolean | Promise); +>testUnwrap3 : Symbol(testUnwrap3, Decl(typeCall.ts, 148, 13)) +>UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 140, 46)) +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 157, 34)) + +declare function myThen( +>myThen : Symbol(myThen, Decl(typeCall.ts, 148, 68)) +>T : Symbol(T, Decl(typeCall.ts, 149, 24)) +>TResult1 : Symbol(TResult1, Decl(typeCall.ts, 149, 26)) +>T : Symbol(T, Decl(typeCall.ts, 149, 24)) +>TResult2 : Symbol(TResult2, Decl(typeCall.ts, 149, 40)) + + prom: Promise, +>prom : Symbol(prom, Decl(typeCall.ts, 149, 59)) +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 157, 34)) +>T : Symbol(T, Decl(typeCall.ts, 149, 24)) + + onfulfilled?: ((value: T) => TResult1) | undefined | null, +>onfulfilled : Symbol(onfulfilled, Decl(typeCall.ts, 150, 25)) +>value : Symbol(value, Decl(typeCall.ts, 151, 24)) +>T : Symbol(T, Decl(typeCall.ts, 149, 24)) +>TResult1 : Symbol(TResult1, Decl(typeCall.ts, 149, 26)) + + onrejected?: ((reason: any) => TResult2) | undefined | null +>onrejected : Symbol(onrejected, Decl(typeCall.ts, 151, 66)) +>reason : Symbol(reason, Decl(typeCall.ts, 152, 23)) +>TResult2 : Symbol(TResult2, Decl(typeCall.ts, 149, 40)) + + ): Promise; +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 157, 34)) +>UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 140, 46)) +>TResult1 : Symbol(TResult1, Decl(typeCall.ts, 149, 26)) +>UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 140, 46)) +>TResult2 : Symbol(TResult2, Decl(typeCall.ts, 149, 40)) + +declare const pr: Promise; +>pr : Symbol(pr, Decl(typeCall.ts, 154, 13)) +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 157, 34)) + +declare function f(x: number): Promise; +>f : Symbol(f, Decl(typeCall.ts, 16, 14), Decl(typeCall.ts, 154, 34)) +>x : Symbol(x, Decl(typeCall.ts, 155, 19)) +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 157, 34)) + +declare function g(x: number): number | Promise; +>g : Symbol(g, Decl(typeCall.ts, 17, 29), Decl(typeCall.ts, 155, 47)) +>x : Symbol(x, Decl(typeCall.ts, 156, 19)) +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 157, 34)) + +const testThen = myThen(pr, f, g); +>testThen : Symbol(testThen, Decl(typeCall.ts, 157, 5)) +>myThen : Symbol(myThen, Decl(typeCall.ts, 148, 68)) +>pr : Symbol(pr, Decl(typeCall.ts, 154, 13)) +>f : Symbol(f, Decl(typeCall.ts, 16, 14), Decl(typeCall.ts, 154, 34)) +>g : Symbol(g, Decl(typeCall.ts, 17, 29), Decl(typeCall.ts, 155, 47)) + +interface Promise { +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 157, 34)) +>T : Symbol(T, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 159, 18)) + + then( +>then : Symbol(Promise.then, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 159, 22)) +>TResult1 : Symbol(TResult1, Decl(typeCall.ts, 160, 9)) +>T : Symbol(T, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 159, 18)) +>TResult2 : Symbol(TResult2, Decl(typeCall.ts, 160, 22)) + + onfulfilled?: ((value: T) => TResult1) | undefined | null, +>onfulfilled : Symbol(onfulfilled, Decl(typeCall.ts, 160, 41)) +>value : Symbol(value, Decl(typeCall.ts, 161, 24)) +>T : Symbol(T, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 159, 18)) +>TResult1 : Symbol(TResult1, Decl(typeCall.ts, 160, 9)) + + onrejected?: ((reason: any) => TResult2) | undefined | null +>onrejected : Symbol(onrejected, Decl(typeCall.ts, 161, 66)) +>reason : Symbol(reason, Decl(typeCall.ts, 162, 23)) +>TResult2 : Symbol(TResult2, Decl(typeCall.ts, 160, 22)) + + ): Promise; +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 157, 34)) +>UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 140, 46)) +>TResult1 : Symbol(TResult1, Decl(typeCall.ts, 160, 9)) +>UnwrapPromise : Symbol(UnwrapPromise, Decl(typeCall.ts, 140, 46)) +>TResult2 : Symbol(TResult2, Decl(typeCall.ts, 160, 22)) +} +// prevents error: Argument of type '(x: number) => number | Promise' is not assignable to parameter of type '(value: number) => string | PromiseLike'; +const tryProm = pr.then((x: number) => { +>tryProm : Symbol(tryProm, Decl(typeCall.ts, 166, 5)) +>pr.then : Symbol(Promise.then, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 159, 22)) +>pr : Symbol(pr, Decl(typeCall.ts, 154, 13)) +>then : Symbol(Promise.then, Decl(lib.d.ts, --, --), Decl(typeCall.ts, 159, 22)) +>x : Symbol(x, Decl(typeCall.ts, 166, 25)) + + if (x < 0) return f(x); +>x : Symbol(x, Decl(typeCall.ts, 166, 25)) +>f : Symbol(f, Decl(typeCall.ts, 16, 14), Decl(typeCall.ts, 154, 34)) +>x : Symbol(x, Decl(typeCall.ts, 166, 25)) + + return x; +>x : Symbol(x, Decl(typeCall.ts, 166, 25)) + +}); + +interface ObjectHasStringIndex { +>ObjectHasStringIndex : Symbol(ObjectHasStringIndex, Decl(typeCall.ts, 169, 3)) + + // (o: T): T[string]; + (o: { [k: string]: any }): '1'; +>o : Symbol(o, Decl(typeCall.ts, 173, 3)) +>k : Symbol(k, Decl(typeCall.ts, 173, 9)) + + (o: {}): '0'; +>o : Symbol(o, Decl(typeCall.ts, 174, 3)) +} +let ObjectHasStringIndexTestT: ObjectHasStringIndex({ [k: string]: 123 }); // '1' +>ObjectHasStringIndexTestT : Symbol(ObjectHasStringIndexTestT, Decl(typeCall.ts, 176, 3)) +>ObjectHasStringIndex : Symbol(ObjectHasStringIndex, Decl(typeCall.ts, 169, 3)) +>k : Symbol(k, Decl(typeCall.ts, 176, 55)) + +let ObjectHasStringIndexTestF: ObjectHasStringIndex({ a: 123 }); // wanted '0', got '1'... so can't match for index, and erroring RHS yields `any`. ouch. +>ObjectHasStringIndexTestF : Symbol(ObjectHasStringIndexTestF, Decl(typeCall.ts, 177, 3)) +>ObjectHasStringIndex : Symbol(ObjectHasStringIndex, Decl(typeCall.ts, 169, 3)) +>a : Symbol(a, Decl(typeCall.ts, 177, 53)) + +type IndexCall { [k: string]: any }, K extends keyof (T())> = T()[K]; +>IndexCall : Symbol(IndexCall, Decl(typeCall.ts, 177, 64)) +>T : Symbol(T, Decl(typeCall.ts, 179, 15)) +>k : Symbol(k, Decl(typeCall.ts, 179, 34)) +>K : Symbol(K, Decl(typeCall.ts, 179, 52)) +>T : Symbol(T, Decl(typeCall.ts, 179, 15)) +>T : Symbol(T, Decl(typeCall.ts, 179, 15)) +>K : Symbol(K, Decl(typeCall.ts, 179, 52)) + +type CallMember any }, K extends keyof T> = T[K](); +>CallMember : Symbol(CallMember, Decl(typeCall.ts, 179, 85)) +>T : Symbol(T, Decl(typeCall.ts, 180, 16)) +>k : Symbol(k, Decl(typeCall.ts, 180, 29)) +>K : Symbol(K, Decl(typeCall.ts, 180, 53)) +>T : Symbol(T, Decl(typeCall.ts, 180, 16)) +>T : Symbol(T, Decl(typeCall.ts, 180, 16)) +>K : Symbol(K, Decl(typeCall.ts, 180, 53)) + +type MappedMemberCall any }> = { [K in keyof T]: T[K]() }; +>MappedMemberCall : Symbol(MappedMemberCall, Decl(typeCall.ts, 180, 82)) +>T : Symbol(T, Decl(typeCall.ts, 181, 22)) +>k : Symbol(k, Decl(typeCall.ts, 181, 35)) +>K : Symbol(K, Decl(typeCall.ts, 181, 65)) +>T : Symbol(T, Decl(typeCall.ts, 181, 22)) +>T : Symbol(T, Decl(typeCall.ts, 181, 22)) +>K : Symbol(K, Decl(typeCall.ts, 181, 65)) + +type HasKey = ( +>HasKey : Symbol(HasKey, Decl(typeCall.ts, 181, 89)) +>T : Symbol(T, Decl(typeCall.ts, 183, 12)) +>Key : Symbol(Key, Decl(typeCall.ts, 183, 14)) + + { [K in keyof T]: 'true' } & +>K : Symbol(K, Decl(typeCall.ts, 184, 5)) +>T : Symbol(T, Decl(typeCall.ts, 183, 12)) + + { [key: string]: 'false' } +>key : Symbol(key, Decl(typeCall.ts, 185, 5)) + +)[Key]; +>Key : Symbol(Key, Decl(typeCall.ts, 183, 14)) + +type HasKindKey any> = HasKey; +>HasKindKey : Symbol(HasKindKey, Decl(typeCall.ts, 186, 7)) +>T : Symbol(T, Decl(typeCall.ts, 188, 16)) +>HasKey : Symbol(HasKey, Decl(typeCall.ts, 181, 89)) +>T : Symbol(T, Decl(typeCall.ts, 188, 16)) + +type MapHasKey any }, Key extends string> = { +>MapHasKey : Symbol(MapHasKey, Decl(typeCall.ts, 188, 59)) +>T : Symbol(T, Decl(typeCall.ts, 189, 15)) +>k : Symbol(k, Decl(typeCall.ts, 189, 28)) +>Key : Symbol(Key, Decl(typeCall.ts, 189, 52)) + + [K in keyof T]: HasKey +>K : Symbol(K, Decl(typeCall.ts, 190, 5)) +>T : Symbol(T, Decl(typeCall.ts, 189, 15)) +>HasKey : Symbol(HasKey, Decl(typeCall.ts, 181, 89)) +>T : Symbol(T, Decl(typeCall.ts, 189, 15)) +>K : Symbol(K, Decl(typeCall.ts, 190, 5)) +>Key : Symbol(Key, Decl(typeCall.ts, 189, 52)) + +}; + +type KeyOfCall any> = keyof (T()); +>KeyOfCall : Symbol(KeyOfCall, Decl(typeCall.ts, 191, 2)) +>T : Symbol(T, Decl(typeCall.ts, 193, 15)) +>T : Symbol(T, Decl(typeCall.ts, 193, 15)) + +type Strip1 any> = { [K in keyof (T())]: T()[K] }; +>Strip1 : Symbol(Strip1, Decl(typeCall.ts, 193, 50)) +>T : Symbol(T, Decl(typeCall.ts, 195, 12)) +>K : Symbol(K, Decl(typeCall.ts, 195, 38)) +>T : Symbol(T, Decl(typeCall.ts, 195, 12)) +>T : Symbol(T, Decl(typeCall.ts, 195, 12)) +>K : Symbol(K, Decl(typeCall.ts, 195, 38)) + +type Strip2 { [k: string]: () => any }> = { [K in keyof (T())]: T()[K]() }; +>Strip2 : Symbol(Strip2, Decl(typeCall.ts, 195, 66)) +>T : Symbol(T, Decl(typeCall.ts, 196, 12)) +>k : Symbol(k, Decl(typeCall.ts, 196, 31)) +>K : Symbol(K, Decl(typeCall.ts, 196, 61)) +>T : Symbol(T, Decl(typeCall.ts, 196, 12)) +>T : Symbol(T, Decl(typeCall.ts, 196, 12)) +>K : Symbol(K, Decl(typeCall.ts, 196, 61)) + +type Obj = { +>Obj : Symbol(Obj, Decl(typeCall.ts, 196, 91)) + + x: () => number, +>x : Symbol(x, Decl(typeCall.ts, 198, 12)) + + z: () => { kind: 'Just', value: string } +>z : Symbol(z, Decl(typeCall.ts, 199, 20)) +>kind : Symbol(kind, Decl(typeCall.ts, 200, 14)) +>value : Symbol(value, Decl(typeCall.ts, 200, 28)) +} + +type T1 = (() => number)(); +>T1 : Symbol(T1, Decl(typeCall.ts, 201, 1)) + +type T7 = CallMember; +>T7 : Symbol(T7, Decl(typeCall.ts, 203, 27)) +>CallMember : Symbol(CallMember, Decl(typeCall.ts, 179, 85)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 196, 91)) + +type T8 = IndexCall<() => Obj, 'x'>; +>T8 : Symbol(T8, Decl(typeCall.ts, 204, 31)) +>IndexCall : Symbol(IndexCall, Decl(typeCall.ts, 177, 64)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 196, 91)) + +type T9 = MappedMemberCall; // fails, unresolved, want { x: number, z: { kind: 'Just', value: string } } +>T9 : Symbol(T9, Decl(typeCall.ts, 205, 36)) +>MappedMemberCall : Symbol(MappedMemberCall, Decl(typeCall.ts, 180, 82)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 196, 91)) + +type T13 = keyof (() => Obj)(); +>T13 : Symbol(T13, Decl(typeCall.ts, 206, 32)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 196, 91)) + +type T14 = KeyOfCall<() => Obj>; +>T14 : Symbol(T14, Decl(typeCall.ts, 207, 31)) +>KeyOfCall : Symbol(KeyOfCall, Decl(typeCall.ts, 191, 2)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 196, 91)) + +type T15 = Obj['z']()['kind']; +>T15 : Symbol(T15, Decl(typeCall.ts, 208, 32)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 196, 91)) + +type T16 = MapHasKey; // fails, unresolved, want { x: 'false', z: 'true' } +>T16 : Symbol(T16, Decl(typeCall.ts, 209, 30)) +>MapHasKey : Symbol(MapHasKey, Decl(typeCall.ts, 188, 59)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 196, 91)) + +type T17 = Strip1<() => Obj>; // fails, unresolved, want { x: () => number, z: () => { kind: 'Just', value: string } } +>T17 : Symbol(T17, Decl(typeCall.ts, 210, 34)) +>Strip1 : Symbol(Strip1, Decl(typeCall.ts, 193, 50)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 196, 91)) + +type T19 = Strip2<() => Obj>; // fails, unresolved, want { x: number, z: { kind: 'Just', value: string } } +>T19 : Symbol(T19, Decl(typeCall.ts, 211, 29)) +>Strip2 : Symbol(Strip2, Decl(typeCall.ts, 195, 66)) +>Obj : Symbol(Obj, Decl(typeCall.ts, 196, 91)) + +let a1: () => string; +>a1 : Symbol(a1, Decl(typeCall.ts, 214, 3)) + +let b1: typeof a1(); +>b1 : Symbol(b1, Decl(typeCall.ts, 215, 3)) +>a1 : Symbol(a1, Decl(typeCall.ts, 214, 3)) + +type Abc any> = T(); +>Abc : Symbol(Abc, Decl(typeCall.ts, 215, 20)) +>T : Symbol(T, Decl(typeCall.ts, 216, 9)) +>T : Symbol(T, Decl(typeCall.ts, 216, 9)) + +let c1: Abc; +>c1 : Symbol(c1, Decl(typeCall.ts, 217, 3)) +>Abc : Symbol(Abc, Decl(typeCall.ts, 215, 20)) +>a1 : Symbol(a1, Decl(typeCall.ts, 214, 3)) + +declare function infer1 any>(x: T): T(); +>infer1 : Symbol(infer1, Decl(typeCall.ts, 217, 23)) +>T : Symbol(T, Decl(typeCall.ts, 219, 24)) +>x : Symbol(x, Decl(typeCall.ts, 219, 45)) +>T : Symbol(T, Decl(typeCall.ts, 219, 24)) +>T : Symbol(T, Decl(typeCall.ts, 219, 24)) + +infer1(null! as () => number); +>infer1 : Symbol(infer1, Decl(typeCall.ts, 217, 23)) + +declare function infer2 any>(x: { a: T }): T(); +>infer2 : Symbol(infer2, Decl(typeCall.ts, 220, 30)) +>T : Symbol(T, Decl(typeCall.ts, 222, 24)) +>x : Symbol(x, Decl(typeCall.ts, 222, 45)) +>a : Symbol(a, Decl(typeCall.ts, 222, 49)) +>T : Symbol(T, Decl(typeCall.ts, 222, 24)) +>T : Symbol(T, Decl(typeCall.ts, 222, 24)) + +infer2(null! as { a: () => number }); +>infer2 : Symbol(infer2, Decl(typeCall.ts, 220, 30)) +>a : Symbol(a, Decl(typeCall.ts, 223, 17)) + +declare function infer3(x: { a: () => T }): T; +>infer3 : Symbol(infer3, Decl(typeCall.ts, 223, 37)) +>T : Symbol(T, Decl(typeCall.ts, 225, 24)) +>x : Symbol(x, Decl(typeCall.ts, 225, 27)) +>a : Symbol(a, Decl(typeCall.ts, 225, 31)) +>T : Symbol(T, Decl(typeCall.ts, 225, 24)) +>T : Symbol(T, Decl(typeCall.ts, 225, 24)) + +infer3(null! as { a: () => number }); +>infer3 : Symbol(infer3, Decl(typeCall.ts, 223, 37)) +>a : Symbol(a, Decl(typeCall.ts, 226, 17)) + +const res3: number = infer3(null! as { a: () => number }); +>res3 : Symbol(res3, Decl(typeCall.ts, 227, 5)) +>infer3 : Symbol(infer3, Decl(typeCall.ts, 223, 37)) +>a : Symbol(a, Decl(typeCall.ts, 227, 38)) + +declare function infer4(x: T, y: () => T): void; +>infer4 : Symbol(infer4, Decl(typeCall.ts, 227, 58)) +>T : Symbol(T, Decl(typeCall.ts, 229, 24)) +>x : Symbol(x, Decl(typeCall.ts, 229, 27)) +>T : Symbol(T, Decl(typeCall.ts, 229, 24)) +>y : Symbol(y, Decl(typeCall.ts, 229, 32)) +>T : Symbol(T, Decl(typeCall.ts, 229, 24)) + +infer4(5, () => 5); +>infer4 : Symbol(infer4, Decl(typeCall.ts, 227, 58)) + +function assignability(x: T, y: () => T) { +>assignability : Symbol(assignability, Decl(typeCall.ts, 230, 19)) +>T : Symbol(T, Decl(typeCall.ts, 232, 23)) +>x : Symbol(x, Decl(typeCall.ts, 232, 26)) +>T : Symbol(T, Decl(typeCall.ts, 232, 23)) +>y : Symbol(y, Decl(typeCall.ts, 232, 31)) +>T : Symbol(T, Decl(typeCall.ts, 232, 23)) + + const a: T = x; +>a : Symbol(a, Decl(typeCall.ts, 233, 9)) +>T : Symbol(T, Decl(typeCall.ts, 232, 23)) +>x : Symbol(x, Decl(typeCall.ts, 232, 26)) + + const b: T = y(); +>b : Symbol(b, Decl(typeCall.ts, 234, 9)) +>T : Symbol(T, Decl(typeCall.ts, 232, 23)) +>y : Symbol(y, Decl(typeCall.ts, 232, 31)) +} + +// function mappedAssignability(x: T, y: CallMember) { +// const d: T() = y; +// } + +// function mappedComparability(x: T, y: CallMember) { +// x === x; +// y === y; +// x === y; +// } + +// type IdMapped = { [K in keyof T]: T[K] } + +// function mappedRelations(x: IdMapped, y: Partial, z: CallMember) { +// x === z; +// y === z; + +// const a: IdMapped = z; +// const b: Partial = z; +// } + +// mappedRelations(null! as Obj, null! as Partial, null! as CallMember); +// mappedRelations(null! as CallMember, null! as CallMember, null! as CallMember); + diff --git a/tests/baselines/reference/typeCall.types b/tests/baselines/reference/typeCall.types new file mode 100644 index 0000000000000..fa0a3c0430290 --- /dev/null +++ b/tests/baselines/reference/typeCall.types @@ -0,0 +1,993 @@ +=== tests/cases/compiler/typeCall.ts === +type F1 = () => 1; +>F1 : F1 + +type a = F1(); +>a : 1 +>F1 : F1 + +type F2 = (a: string) => 1; +>F2 : F2 +>a : string + +type b = F2('foo'); +>b : 1 +>F2 : F2 + +interface F3 { +>F3 : F3 + + (): 1; + (a: number): 2; +>a : number + + (a: string): 3; +>a : string +} +type c = F3(); +>c : 1 +>F3 : F3 + +type d = F3(123); +>d : 2 +>F3 : F3 + +type e = F3('foo'); +>e : 3 +>F3 : F3 + +declare function f4(a: string): 1; +>f4 : (a: string) => 1 +>a : string + +let a = 'foo'; +>a : string +>'foo' : "foo" + +type f = typeof f4(typeof a); +>f : 1 +>f4 : (a: string) => 1 +>a : string + +type g = (() => 1)(); +>g : 1 + +type Id = (v: T) => T; +>Id : Id +>T : T +>v : T +>T : T +>T : T + +type h = Id(123); +>h : 123 +>Id : Id + +type Wrap = Id(T); +>Wrap : Id(T) +>T : T +>Id : Id +>T : T + +type i = Wrap<123>; +>i : 123 +>Wrap : Id(T) + +type F5 = () => () => { a: () => 1; }; +>F5 : F5 +>a : () => 1 + +type j = F5()()['a'](); +>j : 1 +>F5 : F5 + +interface IsPrimitive { +>IsPrimitive : IsPrimitive + + (o: object): '0'; +>o : object + + (o: any): '1'; +>o : any +} +type stringIsPrimitive = IsPrimitive(string); +>stringIsPrimitive : "1" +>IsPrimitive : IsPrimitive + +type regexpIsPrimitive = IsPrimitive(RegExp); +>regexpIsPrimitive : "0" +>IsPrimitive : IsPrimitive +>RegExp : RegExp + +// alternative, pass as parameters +type genericIsPrimitive3 = (v: T) => IsPrimitive(T); +>genericIsPrimitive3 : genericIsPrimitive3 +>T : T +>v : T +>T : T +>IsPrimitive : IsPrimitive +>T : T + +type stringIsPrimitive3 = genericIsPrimitive3(string); +>stringIsPrimitive3 : "1" +>genericIsPrimitive3 : genericIsPrimitive3 + +type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) +>regexpIsPrimitive3 : "0" +>genericIsPrimitive3 : genericIsPrimitive3 +>RegExp : RegExp + +declare function angularFactory R, R extends (foo: T) => T[]>(g: G): R(123); +>angularFactory : R, R extends (foo: T) => T[]>(g: G) => R(123) +>G : G +>args : any[] +>R : R +>R : R +>T : T +>foo : T +>T : T +>T : T +>g : G +>G : G +>R : R + +angularFactory((...args: any[]) => (foo: T) => [foo] as [T]) +>angularFactory((...args: any[]) => (foo: T) => [foo] as [T]) : 123[] +>angularFactory : R, R extends (foo: T) => T[]>(g: G) => R(123) +>(...args: any[]) => (foo: T) => [foo] as [T] : (...args: any[]) => (foo: T) => [T] +>args : any[] +>(foo: T) => [foo] as [T] : (foo: T) => [T] +>T : T +>foo : T +>T : T +>[foo] as [T] : [T] +>[foo] : [T] +>foo : T +>T : T + +interface BoolToString { +>BoolToString : BoolToString + + (v: false & true): never; +>v : false & true +>false : false +>true : true + + (v: false): 'false'; +>v : false +>false : false + + (v: true): 'true'; +>v : true +>true : true + + (v: boolean): 'true' | 'false'; +>v : boolean +} +type strTrue = BoolToString(true); +>strTrue : "true" +>BoolToString : BoolToString +>true : true + +type strFalse = BoolToString(false); +>strFalse : "false" +>BoolToString : BoolToString +>false : false + +type strEither = BoolToString(true | false); +>strEither : "false" | "true" +>BoolToString : BoolToString +>true : true +>false : false + +type strBool = BoolToString(boolean); +>strBool : "false" | "true" +>BoolToString : BoolToString + +type strAny = BoolToString(any); // fails, want the fallback, but yields 'false' +>strAny : "false" +>BoolToString : BoolToString + +// declare function safeDivide< +// B extends number, +// NotZero = ((v: '1') => 'whatever')({ +// (v: 0): '0'; +// (v: number): '1'; +// }(B)) +// >(a: number, b: B): number; +// // Argument of type '"0"' is not assignable to parameter of type '"1"' +// safeDivide(3, 1); +// safeDivide(3, 0); // should error + +type map = any, O extends { [k: string]: T }, T>(fn: Fn, obj: O) => { [P in keyof O]: Fn(O[P]) }; +>map : map +>Fn : Fn +>v : T +>T : T +>O : O +>k : string +>T : T +>T : T +>fn : Fn +>Fn : Fn +>obj : O +>O : O +>P : P +>O : O +>Fn : Fn +>O : O +>P : P + +type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); +>z : { a: [1]; b: [2]; c: [3]; } +>map : map +>T : T +>v : T +>T : T +>T : T +>a : 1 +>b : 2 +>c : 3 + +declare function map(v: T) => any, O extends { [k: string]: T }, T>(fn: Fn, obj: O): { [P in keyof O]: Fn(O[P]) }; +>map : (v: T) => any, O extends { [k: string]: T; }, T>(fn: Fn, obj: O) => { [P in keyof O]: Fn(O[P]); } +>Fn : Fn +>T : T +>v : T +>T : T +>O : O +>k : string +>T : T +>T : T +>fn : Fn +>Fn : Fn +>obj : O +>O : O +>P : P +>O : O +>Fn : Fn +>O : O +>P : P + +let z = map((v: T) => [v] as [T], { a: 1, b: 2, c: 3 } as { a: 1, b: 2, c: 3 }); +>z : { a: [1]; b: [2]; c: [3]; } +>map((v: T) => [v] as [T], { a: 1, b: 2, c: 3 } as { a: 1, b: 2, c: 3 }) : { a: [1]; b: [2]; c: [3]; } +>map : (v: T) => any, O extends { [k: string]: T; }, T>(fn: Fn, obj: O) => { [P in keyof O]: Fn(O[P]); } +>(v: T) => [v] as [T] : (v: T) => [T] +>T : T +>v : T +>T : T +>[v] as [T] : [T] +>[v] : [T] +>v : T +>T : T +>{ a: 1, b: 2, c: 3 } as { a: 1, b: 2, c: 3 } : { a: 1; b: 2; c: 3; } +>{ a: 1, b: 2, c: 3 } : { a: 1; b: 2; c: 3; } +>a : number +>1 : 1 +>b : number +>2 : 2 +>c : number +>3 : 3 +>a : 1 +>b : 2 +>c : 3 + +type Inc = { [k: string]: string; 0:'1', 1:'2', 2:'3', 3:'4', 4:'5', 5:'6', 6:'7', 7:'8', 8:'9' }; +>Inc : Inc +>k : string + +type StringToNumber = { [k: string]: number; 0:0,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8}; +>StringToNumber : StringToNumber +>k : string + +type TupleHasIndex = ({[K in keyof Arr]: '1' } & { [k: string]: '0' })[I]; +>TupleHasIndex : ({ [K in keyof Arr]: "1"; } & { [k: string]: "0"; })[I] +>Arr : Arr +>I : I +>K : K +>Arr : Arr +>k : string +>I : I + +type PathFn, I extends string = '0'> = +>PathFn : { 1: any[({ [K in keyof Arr]: "1"; } & { [k: string]: "0"; })[Inc[I]]]; 0: T; }[({ [K in keyof Arr]: "1"; } & { [k: string]: "0"; })[I]] +>T : T +>k : string +>R : R +>Array : T[] +>I : I + + { 1: PathFn, 0: T }[TupleHasIndex]; +>PathFn : { 1: any[({ [K in keyof Arr]: "1"; } & { [k: string]: "0"; })[Inc[I]]]; 0: T; }[({ [K in keyof Arr]: "1"; } & { [k: string]: "0"; })[I]] +>T : T +>R : R +>StringToNumber : StringToNumber +>I : I +>R : R +>Inc : Inc +>I : I +>T : T +>TupleHasIndex : ({ [K in keyof Arr]: "1"; } & { [k: string]: "0"; })[I] +>R : R +>I : I + +type PathTest = PathFn<{ a: { b: ['c', { d: 'e' }] } }, ['a', 'b', '1', 'd']>; +>PathTest : "e" +>PathFn : { 1: any[({ [K in keyof Arr]: "1"; } & { [k: string]: "0"; })[Inc[I]]]; 0: T; }[({ [K in keyof Arr]: "1"; } & { [k: string]: "0"; })[I]] +>a : { b: ["c", { d: "e"; }]; } +>b : ["c", { d: "e"; }] +>d : "e" + +declare function path>(obj: T, path: R): PathFn; +>path : (obj: T, path: R) => { 1: any[({ [K in keyof Arr]: "1"; } & { [k: string]: "0"; })["1"]]; 0: T; }[({ [K in keyof Arr]: "1"; } & { [k: string]: "0"; })["0"]] +>T : T +>k : string +>R : R +>Array : T[] +>obj : T +>T : T +>path : R +>R : R +>PathFn : { 1: any[({ [K in keyof Arr]: "1"; } & { [k: string]: "0"; })[Inc[I]]]; 0: T; }[({ [K in keyof Arr]: "1"; } & { [k: string]: "0"; })[I]] +>T : T +>R : R + +const obj = null! as { a: { b: ['c', { d: 'e' }] } }; +>obj : { a: { b: ["c", { d: "e"; }]; }; } +>null! as { a: { b: ['c', { d: 'e' }] } } : { a: { b: ["c", { d: "e"; }]; }; } +>null! : never +>null : null +>a : { b: ["c", { d: "e"; }]; } +>b : ["c", { d: "e"; }] +>d : "e" + +const keys = null! as ['a', 'b', '1', 'd']; +>keys : ["a", "b", "1", "d"] +>null! as ['a', 'b', '1', 'd'] : ["a", "b", "1", "d"] +>null! : never +>null : null + +const pathTest = path(obj, keys); +>pathTest : "e" +>path(obj, keys) : "e" +>path : (obj: T, path: R) => { 1: any[({ [K in keyof Arr]: "1"; } & { [k: string]: "0"; })["1"]]; 0: T; }[({ [K in keyof Arr]: "1"; } & { [k: string]: "0"; })["0"]] +>obj : { a: { b: ["c", { d: "e"; }]; }; } +>keys : ["a", "b", "1", "d"] + +// "e" + +// type Reduce< +// Fn extends (previousValue: T, currentValue: R[number], currentIndex?: number, array?: R) => any, +// T, +// R extends any[], +// I extends string = '0' +// > = { 1: Reduce, 0: T }[TupleHasIndex]; +// // fails with error: Cannot read property 'flags' of undefined +// declare function reduce< +// Fn extends (previousValue: any, currentValue: R[number], currentIndex?: number, array?: R) => any, +// R extends any[], +// U, +// I extends string = '0' +// >(callbackfn: Fn, initialValue: U, array: R): Reduce; +// declare function path2>(obj: T, path: R): +// Reduce<(previousValue: Prev, currentValue: Curr, currentIndex?: number, array?: any[]) => Prev[Curr], T, R>; +// const pathTest2 = path2(obj, keys); +// // "e" + +// binary function composition +type Fn1 = (v1: T1[]) => { [k: string]: T1 }; +>Fn1 : Fn1 +>T1 : T1 +>v1 : T1[] +>T1 : T1 +>k : string +>T1 : T1 + +type Fn2 = (v2: { [k: string]: T2 }) => ReadonlyArray; +>Fn2 : Fn2 +>T2 : T2 +>v2 : { [k: string]: T2; } +>k : string +>T2 : T2 +>ReadonlyArray : ReadonlyArray +>T2 : T2 + +let fn1 = null! as Fn1; +>fn1 : Fn1 +>null! as Fn1 : Fn1 +>null! : never +>null : null +>Fn1 : Fn1 + +let fn2 = null! as Fn2; +>fn2 : Fn2 +>null! as Fn2 : Fn2 +>null! : never +>null : null +>Fn2 : Fn2 + +type Fn3 = (v3: T3) => Fn2(Fn1(T3)); +>Fn3 : Fn3 +>T3 : T3 +>v3 : T3 +>T3 : T3 +>Fn2 : Fn2 +>Fn1 : Fn1 +>T3 : T3 + +declare function fn3 T, Fun2 extends (v: T) => any, P1, T>(fun1: Fun1, fun2: Fun2): (...args: any[] /* todo: specify*/) => Fn2(Fn1(P1)); +>fn3 : T, Fun2 extends (v: T) => any, P1, T>(fun1: Fun1, fun2: Fun2) => (...args: any[]) => Fn2(Fn1(P1)) +>Fun1 : Fun1 +>p1 : P1 +>P1 : P1 +>T : T +>Fun2 : Fun2 +>v : T +>T : T +>P1 : P1 +>T : T +>fun1 : Fun1 +>Fun1 : Fun1 +>fun2 : Fun2 +>Fun2 : Fun2 +>args : any[] +>Fn2 : Fn2 +>Fn1 : Fn1 +>P1 : P1 + +let ones = null! as 1[]; +>ones : 1[] +>null! as 1[] : 1[] +>null! : never +>null : null + +type Fn4b = Fn3(typeof ones); +>Fn4b : ReadonlyArray<1> +>Fn3 : Fn3 +>ones : 1[] + +type Fn4c = Fn3(1[]); +>Fn4c : ReadonlyArray<1> +>Fn3 : Fn3 + +let y = fn2(fn1(ones)); +>y : ReadonlyArray<1> +>fn2(fn1(ones)) : ReadonlyArray<1> +>fn2 : Fn2 +>fn1(ones) : { [k: string]: 1; } +>fn1 : Fn1 +>ones : 1[] + +type Y = Fn2(Fn1(1[])); +>Y : ReadonlyArray<1> +>Fn2 : Fn2 +>Fn1 : Fn1 + +// let z2 = fn3(fn1, fn2)(ones); // Cannot read property 'parent' of undefined + +interface isT { +>isT : isT +>T : T + + (v: never): '0'; +>v : never + + (v: T): '1'; +>v : T +>T : T + + (v: any): '0'; +>v : any +} +type Matches = isT(V); +>Matches : isT(V) +>V : V +>T : T +>isT : isT +>T : T +>V : V + +type isBool = isT; +>isBool : isT +>isT : isT + +let falseBool: isBool(false); // 1 +>falseBool : "1" +>isBool : isT +>false : false + +let trueBool: isBool(true); // 1 +>trueBool : "1" +>isBool : isT +>true : true + +let strBool: isBool(string); // 0 +>strBool : "0" +>isBool : isT + +let anyBool: isBool(any); // 0 +>anyBool : "0" +>isBool : isT + +let neverBool: isBool(never); // 0 +>neverBool : "0" +>isBool : isT + +type Assert = { +>Assert : { (v: null | undefined): never; (v: U): U; }(T) +>T : T + + (v: null | undefined): never; +>v : null | undefined +>null : null + + (v: U): U; +>U : U +>v : U +>U : U +>U : U + +}(T); +>T : T + +let assert: Assert; // string +>assert : string +>Assert : { (v: null | undefined): never; (v: U): U; }(T) + +type Minus = { +>Minus : { (v: B): never; (v: U): U; }(A) +>A : A +>B : B + + (v: B): never; +>v : B +>B : B + + (v: U): U; +>U : U +>v : U +>U : U +>U : U + +}(A); +>A : A + +let noNumbers: Minus; // string +>noNumbers : string +>Minus : { (v: B): never; (v: U): U; }(A) + +interface UnwrapPromise { +>UnwrapPromise : UnwrapPromise + + (v: PromiseLike): UnwrapPromise(U); +>U : U +>v : PromiseLike +>PromiseLike : PromiseLike +>U : U +>UnwrapPromise : UnwrapPromise +>U : U + + (v: U): U; +>U : U +>v : U +>U : U +>U : U + +}; +declare const testUnwrap1: UnwrapPromise(string); +>testUnwrap1 : string +>UnwrapPromise : UnwrapPromise + +declare const testUnwrap2: UnwrapPromise(Promise); +>testUnwrap2 : string +>UnwrapPromise : UnwrapPromise +>Promise : Promise + +declare const testUnwrap3: UnwrapPromise(boolean | Promise); +>testUnwrap3 : string | boolean +>UnwrapPromise : UnwrapPromise +>Promise : Promise + +declare function myThen( +>myThen : (prom: Promise, onfulfilled?: ((value: T) => TResult1) | null | undefined, onrejected?: ((reason: any) => TResult2) | null | undefined) => Promise +>T : T +>TResult1 : TResult1 +>T : T +>TResult2 : TResult2 + + prom: Promise, +>prom : Promise +>Promise : Promise +>T : T + + onfulfilled?: ((value: T) => TResult1) | undefined | null, +>onfulfilled : ((value: T) => TResult1) | null | undefined +>value : T +>T : T +>TResult1 : TResult1 +>null : null + + onrejected?: ((reason: any) => TResult2) | undefined | null +>onrejected : ((reason: any) => TResult2) | null | undefined +>reason : any +>TResult2 : TResult2 +>null : null + + ): Promise; +>Promise : Promise +>UnwrapPromise : UnwrapPromise +>TResult1 : TResult1 +>UnwrapPromise : UnwrapPromise +>TResult2 : TResult2 + +declare const pr: Promise; +>pr : Promise +>Promise : Promise + +declare function f(x: number): Promise; +>f : (x: number) => Promise +>x : number +>Promise : Promise + +declare function g(x: number): number | Promise; +>g : (x: number) => number | Promise +>x : number +>Promise : Promise + +const testThen = myThen(pr, f, g); +>testThen : Promise +>myThen(pr, f, g) : Promise +>myThen : (prom: Promise, onfulfilled?: ((value: T) => TResult1) | null | undefined, onrejected?: ((reason: any) => TResult2) | null | undefined) => Promise +>pr : Promise +>f : (x: number) => Promise +>g : (x: number) => number | Promise + +interface Promise { +>Promise : Promise +>T : T + + then( +>then : { (onfulfilled?: ((value: T) => TResult1 | PromiseLike) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike) | null | undefined): Promise; (onfulfilled?: ((value: T) => TResult1) | null | undefined, onrejected?: ((reason: any) => TResult2) | null | undefined): Promise; } +>TResult1 : TResult1 +>T : T +>TResult2 : TResult2 + + onfulfilled?: ((value: T) => TResult1) | undefined | null, +>onfulfilled : ((value: T) => TResult1) | null | undefined +>value : T +>T : T +>TResult1 : TResult1 +>null : null + + onrejected?: ((reason: any) => TResult2) | undefined | null +>onrejected : ((reason: any) => TResult2) | null | undefined +>reason : any +>TResult2 : TResult2 +>null : null + + ): Promise; +>Promise : Promise +>UnwrapPromise : UnwrapPromise +>TResult1 : TResult1 +>UnwrapPromise : UnwrapPromise +>TResult2 : TResult2 +} +// prevents error: Argument of type '(x: number) => number | Promise' is not assignable to parameter of type '(value: number) => string | PromiseLike'; +const tryProm = pr.then((x: number) => { +>tryProm : Promise +>pr.then((x: number) => { if (x < 0) return f(x); return x;}) : Promise +>pr.then : { (onfulfilled?: ((value: number) => TResult1 | PromiseLike) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike) | null | undefined): Promise; (onfulfilled?: ((value: number) => TResult1) | null | undefined, onrejected?: ((reason: any) => TResult2) | null | undefined): Promise; } +>pr : Promise +>then : { (onfulfilled?: ((value: number) => TResult1 | PromiseLike) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike) | null | undefined): Promise; (onfulfilled?: ((value: number) => TResult1) | null | undefined, onrejected?: ((reason: any) => TResult2) | null | undefined): Promise; } +>(x: number) => { if (x < 0) return f(x); return x;} : (x: number) => number | Promise +>x : number + + if (x < 0) return f(x); +>x < 0 : boolean +>x : number +>0 : 0 +>f(x) : Promise +>f : (x: number) => Promise +>x : number + + return x; +>x : number + +}); + +interface ObjectHasStringIndex { +>ObjectHasStringIndex : ObjectHasStringIndex + + // (o: T): T[string]; + (o: { [k: string]: any }): '1'; +>o : { [k: string]: any; } +>k : string + + (o: {}): '0'; +>o : {} +} +let ObjectHasStringIndexTestT: ObjectHasStringIndex({ [k: string]: 123 }); // '1' +>ObjectHasStringIndexTestT : "1" +>ObjectHasStringIndex : ObjectHasStringIndex +>k : string + +let ObjectHasStringIndexTestF: ObjectHasStringIndex({ a: 123 }); // wanted '0', got '1'... so can't match for index, and erroring RHS yields `any`. ouch. +>ObjectHasStringIndexTestF : "1" +>ObjectHasStringIndex : ObjectHasStringIndex +>a : 123 + +type IndexCall { [k: string]: any }, K extends keyof (T())> = T()[K]; +>IndexCall : T()[K] +>T : T +>k : string +>K : K +>T : T +>T : T +>K : K + +type CallMember any }, K extends keyof T> = T[K](); +>CallMember : T[K]() +>T : T +>k : string +>K : K +>T : T +>T : T +>K : K + +type MappedMemberCall any }> = { [K in keyof T]: T[K]() }; +>MappedMemberCall : MappedMemberCall +>T : T +>k : string +>K : K +>T : T +>T : T +>K : K + +type HasKey = ( +>HasKey : ({ [K in keyof T]: "true"; } & { [key: string]: "false"; })[Key] +>T : T +>Key : Key + + { [K in keyof T]: 'true' } & +>K : K +>T : T + + { [key: string]: 'false' } +>key : string + +)[Key]; +>Key : Key + +type HasKindKey any> = HasKey; +>HasKindKey : ({ [K in keyof T]: "true"; } & { [key: string]: "false"; })["kind"] +>T : T +>HasKey : ({ [K in keyof T]: "true"; } & { [key: string]: "false"; })[Key] +>T : T + +type MapHasKey any }, Key extends string> = { +>MapHasKey : MapHasKey +>T : T +>k : string +>Key : Key + + [K in keyof T]: HasKey +>K : K +>T : T +>HasKey : ({ [K in keyof T]: "true"; } & { [key: string]: "false"; })[Key] +>T : T +>K : K +>Key : Key + +}; + +type KeyOfCall any> = keyof (T()); +>KeyOfCall : keyof T() +>T : T +>T : T + +type Strip1 any> = { [K in keyof (T())]: T()[K] }; +>Strip1 : Strip1 +>T : T +>K : K +>T : T +>T : T +>K : K + +type Strip2 { [k: string]: () => any }> = { [K in keyof (T())]: T()[K]() }; +>Strip2 : Strip2 +>T : T +>k : string +>K : K +>T : T +>T : T +>K : K + +type Obj = { +>Obj : Obj + + x: () => number, +>x : () => number + + z: () => { kind: 'Just', value: string } +>z : () => { kind: "Just"; value: string; } +>kind : "Just" +>value : string +} + +type T1 = (() => number)(); +>T1 : number + +type T7 = CallMember; +>T7 : number +>CallMember : T[K]() +>Obj : Obj + +type T8 = IndexCall<() => Obj, 'x'>; +>T8 : () => number +>IndexCall : T()[K] +>Obj : Obj + +type T9 = MappedMemberCall; // fails, unresolved, want { x: number, z: { kind: 'Just', value: string } } +>T9 : MappedMemberCall +>MappedMemberCall : MappedMemberCall +>Obj : Obj + +type T13 = keyof (() => Obj)(); +>T13 : "x" | "z" +>Obj : Obj + +type T14 = KeyOfCall<() => Obj>; +>T14 : "x" | "z" +>KeyOfCall : keyof T() +>Obj : Obj + +type T15 = Obj['z']()['kind']; +>T15 : "Just" +>Obj : Obj + +type T16 = MapHasKey; // fails, unresolved, want { x: 'false', z: 'true' } +>T16 : MapHasKey +>MapHasKey : MapHasKey +>Obj : Obj + +type T17 = Strip1<() => Obj>; // fails, unresolved, want { x: () => number, z: () => { kind: 'Just', value: string } } +>T17 : Strip1<() => Obj> +>Strip1 : Strip1 +>Obj : Obj + +type T19 = Strip2<() => Obj>; // fails, unresolved, want { x: number, z: { kind: 'Just', value: string } } +>T19 : Strip2<() => Obj> +>Strip2 : Strip2 +>Obj : Obj + +let a1: () => string; +>a1 : () => string + +let b1: typeof a1(); +>b1 : string +>a1 : () => string + +type Abc any> = T(); +>Abc : T() +>T : T +>T : T + +let c1: Abc; +>c1 : string +>Abc : T() +>a1 : () => string + +declare function infer1 any>(x: T): T(); +>infer1 : any>(x: T) => T() +>T : T +>x : T +>T : T +>T : T + +infer1(null! as () => number); +>infer1(null! as () => number) : number +>infer1 : any>(x: T) => T() +>null! as () => number : () => number +>null! : never +>null : null + +declare function infer2 any>(x: { a: T }): T(); +>infer2 : any>(x: { a: T; }) => T() +>T : T +>x : { a: T; } +>a : T +>T : T +>T : T + +infer2(null! as { a: () => number }); +>infer2(null! as { a: () => number }) : number +>infer2 : any>(x: { a: T; }) => T() +>null! as { a: () => number } : { a: () => number; } +>null! : never +>null : null +>a : () => number + +declare function infer3(x: { a: () => T }): T; +>infer3 : (x: { a: () => T; }) => T +>T : T +>x : { a: () => T; } +>a : () => T +>T : T +>T : T + +infer3(null! as { a: () => number }); +>infer3(null! as { a: () => number }) : number +>infer3 : (x: { a: () => T; }) => T +>null! as { a: () => number } : { a: () => number; } +>null! : never +>null : null +>a : () => number + +const res3: number = infer3(null! as { a: () => number }); +>res3 : number +>infer3(null! as { a: () => number }) : number +>infer3 : (x: { a: () => T; }) => T +>null! as { a: () => number } : { a: () => number; } +>null! : never +>null : null +>a : () => number + +declare function infer4(x: T, y: () => T): void; +>infer4 : (x: T, y: () => T) => void +>T : T +>x : T +>T : T +>y : () => T +>T : T + +infer4(5, () => 5); +>infer4(5, () => 5) : void +>infer4 : (x: T, y: () => T) => void +>5 : 5 +>() => 5 : () => number +>5 : 5 + +function assignability(x: T, y: () => T) { +>assignability : (x: T, y: () => T) => void +>T : T +>x : T +>T : T +>y : () => T +>T : T + + const a: T = x; +>a : T +>T : T +>x : T + + const b: T = y(); +>b : T +>T : T +>y() : T +>y : () => T +} + +// function mappedAssignability(x: T, y: CallMember) { +// const d: T() = y; +// } + +// function mappedComparability(x: T, y: CallMember) { +// x === x; +// y === y; +// x === y; +// } + +// type IdMapped = { [K in keyof T]: T[K] } + +// function mappedRelations(x: IdMapped, y: Partial, z: CallMember) { +// x === z; +// y === z; + +// const a: IdMapped = z; +// const b: Partial = z; +// } + +// mappedRelations(null! as Obj, null! as Partial, null! as CallMember); +// mappedRelations(null! as CallMember, null! as CallMember, null! as CallMember); + diff --git a/tests/baselines/reference/typeCallErrors.errors.txt b/tests/baselines/reference/typeCallErrors.errors.txt new file mode 100644 index 0000000000000..8e4e2510a1bd5 --- /dev/null +++ b/tests/baselines/reference/typeCallErrors.errors.txt @@ -0,0 +1,32 @@ +tests/cases/compiler/typeCallErrors.ts(8,16): error TS2345: Argument of type '1' is not assignable to parameter of type 'number[]'. +tests/cases/compiler/typeCallErrors.ts(9,17): error TS2345: Argument of type '1' is not assignable to parameter of type 'number[]'. +tests/cases/compiler/typeCallErrors.ts(10,18): error TS2345: Argument of type '1' is not assignable to parameter of type 'number[]'. +tests/cases/compiler/typeCallErrors.ts(15,5): error TS2365: Operator '===' cannot be applied to types 'T' and '() => T'. + + +==== tests/cases/compiler/typeCallErrors.ts (4 errors) ==== + // binary function composition + type Fn1 = (v1: T1[]) => { [k: string]: T1 }; + type Fn2 = (v2: { [k: string]: T2 }) => ReadonlyArray; + let fn1 = null! as Fn1; + let fn2 = null! as Fn2; + type Fn3 = (v3: T3) => Fn2(Fn1(T3)); + let ones = null! as 1[]; + type Fn4 = Fn3(1); // errors, ok + ~ +!!! error TS2345: Argument of type '1' is not assignable to parameter of type 'number[]'. + let x = fn2(fn1(1)); // errors with not assignable, ok + ~ +!!! error TS2345: Argument of type '1' is not assignable to parameter of type 'number[]'. + type X = Fn2(Fn1(1)); // errors with not assignable, ok + ~ +!!! error TS2345: Argument of type '1' is not assignable to parameter of type 'number[]'. + + function comparability(x: T, y: () => T) { + x === x; + y === y; + x === y; // rightfully errors + ~~~~~~~ +!!! error TS2365: Operator '===' cannot be applied to types 'T' and '() => T'. + } + \ No newline at end of file diff --git a/tests/baselines/reference/typeCallErrors.js b/tests/baselines/reference/typeCallErrors.js new file mode 100644 index 0000000000000..7f1c66a0c74af --- /dev/null +++ b/tests/baselines/reference/typeCallErrors.js @@ -0,0 +1,29 @@ +//// [typeCallErrors.ts] +// binary function composition +type Fn1 = (v1: T1[]) => { [k: string]: T1 }; +type Fn2 = (v2: { [k: string]: T2 }) => ReadonlyArray; +let fn1 = null! as Fn1; +let fn2 = null! as Fn2; +type Fn3 = (v3: T3) => Fn2(Fn1(T3)); +let ones = null! as 1[]; +type Fn4 = Fn3(1); // errors, ok +let x = fn2(fn1(1)); // errors with not assignable, ok +type X = Fn2(Fn1(1)); // errors with not assignable, ok + +function comparability(x: T, y: () => T) { + x === x; + y === y; + x === y; // rightfully errors +} + + +//// [typeCallErrors.js] +var fn1 = null; +var fn2 = null; +var ones = null; +var x = fn2(fn1(1)); // errors with not assignable, ok +function comparability(x, y) { + x === x; + y === y; + x === y; // rightfully errors +} diff --git a/tests/cases/compiler/contextualTypingWithGenericAndNonGenericSignature.ts b/tests/cases/compiler/contextualTypingWithGenericAndNonGenericSignature.ts index d480bf16b82d8..2faf17c66bbd9 100644 --- a/tests/cases/compiler/contextualTypingWithGenericAndNonGenericSignature.ts +++ b/tests/cases/compiler/contextualTypingWithGenericAndNonGenericSignature.ts @@ -1,7 +1,7 @@ //• If e is a FunctionExpression or ArrowFunctionExpression with no type parameters and no parameter or return type annotations, and T is a function type with EXACTLY ONE non - generic call signature, then any inferences made for type parameters referenced by the parameters of T’s call signature are fixed(section 4.12.2) and e is processed with the contextual type T, as described in section 4.9.3. var f2: { - (x: string, y: number): string; + (x: string, y: number): string (x: T, y: U): T }; diff --git a/tests/cases/compiler/overloadSelection.ts b/tests/cases/compiler/overloadSelection.ts new file mode 100644 index 0000000000000..2575dc5ac60c1 --- /dev/null +++ b/tests/cases/compiler/overloadSelection.ts @@ -0,0 +1,8 @@ +// @allowSyntheticDefaultImports: true + +interface Match { + (o: object): 0; + (o: any): 1; +} +type Wrap = (v: T) => Match(T); +type A = Wrap(RegExp); diff --git a/tests/cases/compiler/typeAliasDeclarationEmit.ts b/tests/cases/compiler/typeAliasDeclarationEmit.ts index be7e40453f60d..4edfd36775c7e 100644 --- a/tests/cases/compiler/typeAliasDeclarationEmit.ts +++ b/tests/cases/compiler/typeAliasDeclarationEmit.ts @@ -1,6 +1,7 @@ // @target: ES5 // @module: AMD // @declaration: true +// @allowSyntheticDefaultImports: true export type callback = () => T; diff --git a/tests/cases/compiler/typeCall.ts b/tests/cases/compiler/typeCall.ts new file mode 100644 index 0000000000000..a90749930a7c4 --- /dev/null +++ b/tests/cases/compiler/typeCall.ts @@ -0,0 +1,263 @@ +// @allowSyntheticDefaultImports: true +// @strictNullChecks: true +// @noimplicitany: true + +type F1 = () => 1; +type a = F1(); + +type F2 = (a: string) => 1; +type b = F2('foo'); + +interface F3 { + (): 1; + (a: number): 2; + (a: string): 3; +} +type c = F3(); +type d = F3(123); +type e = F3('foo'); + +declare function f4(a: string): 1; +let a = 'foo'; +type f = typeof f4(typeof a); + +type g = (() => 1)(); + +type Id = (v: T) => T; +type h = Id(123); + +type Wrap = Id(T); +type i = Wrap<123>; + +type F5 = () => () => { a: () => 1; }; +type j = F5()()['a'](); + +interface IsPrimitive { + (o: object): '0'; + (o: any): '1'; +} +type stringIsPrimitive = IsPrimitive(string); +type regexpIsPrimitive = IsPrimitive(RegExp); + +// alternative, pass as parameters +type genericIsPrimitive3 = (v: T) => IsPrimitive(T); +type stringIsPrimitive3 = genericIsPrimitive3(string); +type regexpIsPrimitive3 = genericIsPrimitive3(RegExp) + +declare function angularFactory R, R extends (foo: T) => T[]>(g: G): R(123); +angularFactory((...args: any[]) => (foo: T) => [foo] as [T]) + +interface BoolToString { + (v: false & true): never; + (v: false): 'false'; + (v: true): 'true'; + (v: boolean): 'true' | 'false'; +} +type strTrue = BoolToString(true); +type strFalse = BoolToString(false); +type strEither = BoolToString(true | false); +type strBool = BoolToString(boolean); +type strAny = BoolToString(any); // fails, want the fallback, but yields 'false' + +// declare function safeDivide< +// B extends number, +// NotZero = ((v: '1') => 'whatever')({ +// (v: 0): '0'; +// (v: number): '1'; +// }(B)) +// >(a: number, b: B): number; +// // Argument of type '"0"' is not assignable to parameter of type '"1"' +// safeDivide(3, 1); +// safeDivide(3, 0); // should error + +type map = any, O extends { [k: string]: T }, T>(fn: Fn, obj: O) => { [P in keyof O]: Fn(O[P]) }; +type z = map((v: T) => [T], { a: 1, b: 2, c: 3 }); +declare function map(v: T) => any, O extends { [k: string]: T }, T>(fn: Fn, obj: O): { [P in keyof O]: Fn(O[P]) }; +let z = map((v: T) => [v] as [T], { a: 1, b: 2, c: 3 } as { a: 1, b: 2, c: 3 }); + +type Inc = { [k: string]: string; 0:'1', 1:'2', 2:'3', 3:'4', 4:'5', 5:'6', 6:'7', 7:'8', 8:'9' }; +type StringToNumber = { [k: string]: number; 0:0,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8}; +type TupleHasIndex = ({[K in keyof Arr]: '1' } & { [k: string]: '0' })[I]; +type PathFn, I extends string = '0'> = + { 1: PathFn, 0: T }[TupleHasIndex]; +type PathTest = PathFn<{ a: { b: ['c', { d: 'e' }] } }, ['a', 'b', '1', 'd']>; +declare function path>(obj: T, path: R): PathFn; +const obj = null! as { a: { b: ['c', { d: 'e' }] } }; +const keys = null! as ['a', 'b', '1', 'd']; +const pathTest = path(obj, keys); +// "e" + +// type Reduce< +// Fn extends (previousValue: T, currentValue: R[number], currentIndex?: number, array?: R) => any, +// T, +// R extends any[], +// I extends string = '0' +// > = { 1: Reduce, 0: T }[TupleHasIndex]; +// // fails with error: Cannot read property 'flags' of undefined +// declare function reduce< +// Fn extends (previousValue: any, currentValue: R[number], currentIndex?: number, array?: R) => any, +// R extends any[], +// U, +// I extends string = '0' +// >(callbackfn: Fn, initialValue: U, array: R): Reduce; +// declare function path2>(obj: T, path: R): +// Reduce<(previousValue: Prev, currentValue: Curr, currentIndex?: number, array?: any[]) => Prev[Curr], T, R>; +// const pathTest2 = path2(obj, keys); +// // "e" + +// binary function composition +type Fn1 = (v1: T1[]) => { [k: string]: T1 }; +type Fn2 = (v2: { [k: string]: T2 }) => ReadonlyArray; +let fn1 = null! as Fn1; +let fn2 = null! as Fn2; +type Fn3 = (v3: T3) => Fn2(Fn1(T3)); +declare function fn3 T, Fun2 extends (v: T) => any, P1, T>(fun1: Fun1, fun2: Fun2): (...args: any[] /* todo: specify*/) => Fn2(Fn1(P1)); +let ones = null! as 1[]; +type Fn4b = Fn3(typeof ones); +type Fn4c = Fn3(1[]); +let y = fn2(fn1(ones)); +type Y = Fn2(Fn1(1[])); +// let z2 = fn3(fn1, fn2)(ones); // Cannot read property 'parent' of undefined + +interface isT { + (v: never): '0'; + (v: T): '1'; + (v: any): '0'; +} +type Matches = isT(V); +type isBool = isT; +let falseBool: isBool(false); // 1 +let trueBool: isBool(true); // 1 +let strBool: isBool(string); // 0 +let anyBool: isBool(any); // 0 +let neverBool: isBool(never); // 0 + +type Assert = { + (v: null | undefined): never; + (v: U): U; +}(T); +let assert: Assert; // string + +type Minus = { + (v: B): never; + (v: U): U; +}(A); +let noNumbers: Minus; // string + +interface UnwrapPromise { + (v: PromiseLike): UnwrapPromise(U); + (v: U): U; +}; +declare const testUnwrap1: UnwrapPromise(string); +declare const testUnwrap2: UnwrapPromise(Promise); +declare const testUnwrap3: UnwrapPromise(boolean | Promise); +declare function myThen( + prom: Promise, + onfulfilled?: ((value: T) => TResult1) | undefined | null, + onrejected?: ((reason: any) => TResult2) | undefined | null + ): Promise; +declare const pr: Promise; +declare function f(x: number): Promise; +declare function g(x: number): number | Promise; +const testThen = myThen(pr, f, g); + +interface Promise { + then( + onfulfilled?: ((value: T) => TResult1) | undefined | null, + onrejected?: ((reason: any) => TResult2) | undefined | null + ): Promise; +} +// prevents error: Argument of type '(x: number) => number | Promise' is not assignable to parameter of type '(value: number) => string | PromiseLike'; +const tryProm = pr.then((x: number) => { + if (x < 0) return f(x); + return x; +}); + +interface ObjectHasStringIndex { + // (o: T): T[string]; + (o: { [k: string]: any }): '1'; + (o: {}): '0'; +} +let ObjectHasStringIndexTestT: ObjectHasStringIndex({ [k: string]: 123 }); // '1' +let ObjectHasStringIndexTestF: ObjectHasStringIndex({ a: 123 }); // wanted '0', got '1'... so can't match for index, and erroring RHS yields `any`. ouch. + +type IndexCall { [k: string]: any }, K extends keyof (T())> = T()[K]; +type CallMember any }, K extends keyof T> = T[K](); +type MappedMemberCall any }> = { [K in keyof T]: T[K]() }; + +type HasKey = ( + { [K in keyof T]: 'true' } & + { [key: string]: 'false' } +)[Key]; + +type HasKindKey any> = HasKey; +type MapHasKey any }, Key extends string> = { + [K in keyof T]: HasKey +}; + +type KeyOfCall any> = keyof (T()); + +type Strip1 any> = { [K in keyof (T())]: T()[K] }; +type Strip2 { [k: string]: () => any }> = { [K in keyof (T())]: T()[K]() }; + +type Obj = { + x: () => number, + z: () => { kind: 'Just', value: string } +} + +type T1 = (() => number)(); +type T7 = CallMember; +type T8 = IndexCall<() => Obj, 'x'>; +type T9 = MappedMemberCall; // fails, unresolved, want { x: number, z: { kind: 'Just', value: string } } +type T13 = keyof (() => Obj)(); +type T14 = KeyOfCall<() => Obj>; +type T15 = Obj['z']()['kind']; +type T16 = MapHasKey; // fails, unresolved, want { x: 'false', z: 'true' } +type T17 = Strip1<() => Obj>; // fails, unresolved, want { x: () => number, z: () => { kind: 'Just', value: string } } +type T19 = Strip2<() => Obj>; // fails, unresolved, want { x: number, z: { kind: 'Just', value: string } } + +let a1: () => string; +let b1: typeof a1(); +type Abc any> = T(); +let c1: Abc; + +declare function infer1 any>(x: T): T(); +infer1(null! as () => number); + +declare function infer2 any>(x: { a: T }): T(); +infer2(null! as { a: () => number }); + +declare function infer3(x: { a: () => T }): T; +infer3(null! as { a: () => number }); +const res3: number = infer3(null! as { a: () => number }); + +declare function infer4(x: T, y: () => T): void; +infer4(5, () => 5); + +function assignability(x: T, y: () => T) { + const a: T = x; + const b: T = y(); +} + +// function mappedAssignability(x: T, y: CallMember) { +// const d: T() = y; +// } + +// function mappedComparability(x: T, y: CallMember) { +// x === x; +// y === y; +// x === y; +// } + +// type IdMapped = { [K in keyof T]: T[K] } + +// function mappedRelations(x: IdMapped, y: Partial, z: CallMember) { +// x === z; +// y === z; + +// const a: IdMapped = z; +// const b: Partial = z; +// } + +// mappedRelations(null! as Obj, null! as Partial, null! as CallMember); +// mappedRelations(null! as CallMember, null! as CallMember, null! as CallMember); diff --git a/tests/cases/compiler/typeCallErrors.ts b/tests/cases/compiler/typeCallErrors.ts new file mode 100644 index 0000000000000..e83a3d0183567 --- /dev/null +++ b/tests/cases/compiler/typeCallErrors.ts @@ -0,0 +1,16 @@ +// binary function composition +type Fn1 = (v1: T1[]) => { [k: string]: T1 }; +type Fn2 = (v2: { [k: string]: T2 }) => ReadonlyArray; +let fn1 = null! as Fn1; +let fn2 = null! as Fn2; +type Fn3 = (v3: T3) => Fn2(Fn1(T3)); +let ones = null! as 1[]; +type Fn4 = Fn3(1); // errors, ok +let x = fn2(fn1(1)); // errors with not assignable, ok +type X = Fn2(Fn1(1)); // errors with not assignable, ok + +function comparability(x: T, y: () => T) { + x === x; + y === y; + x === y; // rightfully errors +} diff --git a/tests/cases/conformance/types/rest/objectRestNegative.ts b/tests/cases/conformance/types/rest/objectRestNegative.ts index 13d214e453de4..fd224dcb93080 100644 --- a/tests/cases/conformance/types/rest/objectRestNegative.ts +++ b/tests/cases/conformance/types/rest/objectRestNegative.ts @@ -14,5 +14,5 @@ function generic(t: T) { return rest; } -let rest: { b: string } +let rest: { b: string }; ({a, ...rest.b + rest.b} = o);