mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-18 07:29:16 -05:00
Merge pull request #16305 from Microsoft/contextualGenericTypes
Contextual generic function types
This commit is contained in:
@@ -10261,7 +10261,7 @@ namespace ts {
|
||||
const objectFlags = getObjectFlags(type);
|
||||
return !!(type.flags & TypeFlags.TypeVariable ||
|
||||
objectFlags & ObjectFlags.Reference && forEach((<TypeReference>type).typeArguments, couldContainTypeVariables) ||
|
||||
objectFlags & ObjectFlags.Anonymous && type.symbol && type.symbol.flags & (SymbolFlags.Method | SymbolFlags.TypeLiteral | SymbolFlags.Class) ||
|
||||
objectFlags & ObjectFlags.Anonymous && type.symbol && type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.TypeLiteral | SymbolFlags.Class) ||
|
||||
objectFlags & ObjectFlags.Mapped ||
|
||||
type.flags & TypeFlags.UnionOrIntersection && couldUnionOrIntersectionContainTypeVariables(<UnionOrIntersectionType>type));
|
||||
}
|
||||
@@ -13066,13 +13066,13 @@ namespace ts {
|
||||
return node ? node.contextualMapper : identityMapper;
|
||||
}
|
||||
|
||||
// If the given type is an object or union type, if that type has a single signature, and if
|
||||
// that signature is non-generic, return the signature. Otherwise return undefined.
|
||||
function getNonGenericSignature(type: Type, node: FunctionExpression | ArrowFunction | MethodDeclaration): Signature {
|
||||
// If the given type is an object or union type with a single signature, and if that signature has at
|
||||
// least as many parameters as the given function, return the signature. Otherwise return undefined.
|
||||
function getContextualCallSignature(type: Type, node: FunctionExpression | ArrowFunction | MethodDeclaration): Signature {
|
||||
const signatures = getSignaturesOfStructuredType(type, SignatureKind.Call);
|
||||
if (signatures.length === 1) {
|
||||
const signature = signatures[0];
|
||||
if (!signature.typeParameters && !isAritySmaller(signature, node)) {
|
||||
if (!isAritySmaller(signature, node)) {
|
||||
return signature;
|
||||
}
|
||||
}
|
||||
@@ -13123,12 +13123,12 @@ namespace ts {
|
||||
return undefined;
|
||||
}
|
||||
if (!(type.flags & TypeFlags.Union)) {
|
||||
return getNonGenericSignature(type, node);
|
||||
return getContextualCallSignature(type, node);
|
||||
}
|
||||
let signatureList: Signature[];
|
||||
const types = (<UnionType>type).types;
|
||||
for (const current of types) {
|
||||
const signature = getNonGenericSignature(current, node);
|
||||
const signature = getContextualCallSignature(current, node);
|
||||
if (signature) {
|
||||
if (!signatureList) {
|
||||
// This signature will contribute to contextual union signature
|
||||
@@ -14988,11 +14988,21 @@ namespace ts {
|
||||
// We clone the contextual mapper to avoid disturbing a resolution in progress for an
|
||||
// outer call expression. Effectively we just want a snapshot of whatever has been
|
||||
// inferred for any outer call expression so far.
|
||||
const mapper = cloneTypeMapper(getContextualMapper(node));
|
||||
const instantiatedType = instantiateType(contextualType, mapper);
|
||||
const returnType = getReturnTypeOfSignature(signature);
|
||||
// Inferences made from return types have lower priority than all other inferences.
|
||||
inferTypes(context.inferences, instantiatedType, returnType, InferencePriority.ReturnType);
|
||||
const instantiatedType = instantiateType(contextualType, cloneTypeMapper(getContextualMapper(node)));
|
||||
// If the contextual type is a generic pure function type, we instantiate the type with
|
||||
// its own type parameters and type arguments. This ensures that the type parameters are
|
||||
// not erased to type any during type inference such that they can be inferred as actual
|
||||
// types from the contextual type. For example:
|
||||
// declare function arrayMap<T, U>(f: (x: T) => U): (a: T[]) => U[];
|
||||
// const boxElements: <A>(a: A[]) => { value: A }[] = arrayMap(value => ({ value }));
|
||||
// Above, the type of the 'value' parameter is inferred to be 'A'.
|
||||
const contextualSignature = getSingleCallSignature(instantiatedType);
|
||||
const inferenceSourceType = contextualSignature && contextualSignature.typeParameters ?
|
||||
getOrCreateTypeFromSignature(getSignatureInstantiation(contextualSignature, contextualSignature.typeParameters)) :
|
||||
instantiatedType;
|
||||
const inferenceTargetType = getReturnTypeOfSignature(signature);
|
||||
// Inferences made from return types have lower priority than all other inferences.
|
||||
inferTypes(context.inferences, inferenceSourceType, inferenceTargetType, InferencePriority.ReturnType);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user