diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e1736bc9ab..85c2875ff5 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4937,6 +4937,10 @@ namespace ts { return type.resolvedApparentType || (type.resolvedApparentType = getTypeWithThisArgument(type, type)); } + function getApparentTypeOfReturnType(type: ReturnType) { + return type.resolvedApparentType || (type.resolvedApparentType = getReturnType(getApparentType(type.type))); + } + /** * For a type parameter, return the base constraint of the type parameter. For the string, number, * boolean, and symbol primitive types, return the corresponding object types. Otherwise return the @@ -4945,6 +4949,7 @@ namespace ts { function getApparentType(type: Type): Type { const t = type.flags & TypeFlags.TypeVariable ? getBaseConstraintOfType(type) || emptyObjectType : type; return t.flags & TypeFlags.Intersection ? getApparentTypeOfIntersectionType(t) : + t.flags & TypeFlags.Return ? getApparentTypeOfReturnType(t) : t.flags & TypeFlags.StringLike ? globalStringType : t.flags & TypeFlags.NumberLike ? globalNumberType : t.flags & TypeFlags.BooleanLike ? globalBooleanType : @@ -6188,6 +6193,29 @@ namespace ts { return links.resolvedType; } + function getTypeFromReturnOperatorNode(node: ReturnOperatorNode) { + const links = getNodeLinks(node); + if (!links.resolvedType) { + links.resolvedType = getReturnType(getTypeFromTypeNode(node.type)); + } + return links.resolvedType; + } + + function getReturnType(type: Type): Type { + if (maybeTypeOfKind(type, TypeFlags.TypeVariable)) { + return getReturnTypeForGenericType(type as TypeVariable | UnionOrIntersectionType); + } + return getUnionType(map(getSignaturesOfType(type, SignatureKind.Call), getReturnTypeOfSignature)); + } + + function getReturnTypeForGenericType(type: TypeVariable | UnionOrIntersectionType): Type { + if (!type.resolvedReturnType) { + type.resolvedReturnType = createType(TypeFlags.Return); + type.resolvedReturnType.type = type; + } + return type.resolvedReturnType; + } + function createIndexedAccessType(objectType: Type, indexType: Type) { const type = createType(TypeFlags.IndexedAccess); type.objectType = objectType; @@ -6595,7 +6623,9 @@ namespace ts { case SyntaxKind.JSDocFunctionType: return getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node); case SyntaxKind.TypeOperator: - return getTypeFromTypeOperatorNode(node); + return getTypeFromTypeOperatorNode(node as TypeOperatorNode); + case SyntaxKind.ReturnOperator: + return getTypeFromReturnOperatorNode(node as ReturnOperatorNode); case SyntaxKind.IndexedAccessType: return getTypeFromIndexedAccessTypeNode(node); case SyntaxKind.MappedType: @@ -6962,6 +6992,9 @@ namespace ts { if (type.flags & TypeFlags.Index) { return getIndexType(instantiateType((type).type, mapper)); } + if (type.flags & TypeFlags.Return) { + return getReturnType(instantiateType((type).type, mapper)); + } if (type.flags & TypeFlags.IndexedAccess) { return getIndexedAccessType(instantiateType((type).objectType, mapper), instantiateType((type).indexType, mapper)); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 5d43b01338..c729e27824 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2830,6 +2830,7 @@ /* @internal */ ContainsAnyFunctionType = 1 << 23, // Type is or contains object literal type NonPrimitive = 1 << 24, // intrinsic object type + Return = 1 << 25, // Return type of callable (never for uncallable types) /* @internal */ Nullable = Undefined | Null, @@ -2970,6 +2971,8 @@ /* @internal */ resolvedIndexType: IndexType; /* @internal */ + resolvedReturnType: ReturnType; + /* @internal */ resolvedBaseConstraint: Type; /* @internal */ couldContainTypeVariables: boolean; @@ -3037,6 +3040,8 @@ resolvedBaseConstraint: Type; /* @internal */ resolvedIndexType: IndexType; + /* @internal */ + resolvedReturnType: ReturnType; } // Type parameters (TypeFlags.TypeParameter) @@ -3063,6 +3068,13 @@ type: TypeVariable | UnionOrIntersectionType; } + // return T types (TypeFlags.Return) + export interface ReturnType extends Type { + type: TypeVariable | UnionOrIntersectionType; + /* @internal */ + resolvedApparentType: Type; + } + export const enum SignatureKind { Call, Construct,