Fix type variable leaks and cache inconsistencies (#61668)

This commit is contained in:
Anders Hejlsberg 2025-06-09 14:20:27 -07:00 committed by GitHub
parent cb38d99d08
commit 34d1ea68f6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 1069 additions and 105 deletions

View File

@ -1009,7 +1009,6 @@ import {
SignatureFlags,
SignatureKind,
singleElementArray,
SingleSignatureType,
skipOuterExpressions,
skipParentheses,
skipTrivia,
@ -7291,7 +7290,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
const abstractSignatures = filter(resolved.constructSignatures, signature => !!(signature.flags & SignatureFlags.Abstract));
if (some(abstractSignatures)) {
const types = map(abstractSignatures, s => getOrCreateTypeFromSignature(s));
const types = map(abstractSignatures, getOrCreateTypeFromSignature);
// count the number of type elements excluding abstract constructors
const typeElementCount = resolved.callSignatures.length +
(resolved.constructSignatures.length - abstractSignatures.length) +
@ -16415,15 +16414,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
return undefined;
}
function getSignatureInstantiation(signature: Signature, typeArguments: readonly Type[] | undefined, isJavascript: boolean, inferredTypeParameters?: readonly TypeParameter[]): Signature {
function getSignatureInstantiation(signature: Signature, typeArguments: Type[] | undefined, isJavascript: boolean, inferredTypeParameters?: readonly TypeParameter[]): Signature {
const instantiatedSignature = getSignatureInstantiationWithoutFillingInTypeArguments(signature, fillMissingTypeArguments(typeArguments, signature.typeParameters, getMinTypeArgumentCount(signature.typeParameters), isJavascript));
if (inferredTypeParameters) {
const returnSignature = getSingleCallOrConstructSignature(getReturnTypeOfSignature(instantiatedSignature));
if (returnSignature) {
const newReturnSignature = cloneSignature(returnSignature);
newReturnSignature.typeParameters = inferredTypeParameters;
const newReturnType = getOrCreateTypeFromSignature(newReturnSignature) as AnonymousType;
newReturnType.mapper = instantiatedSignature.mapper;
const newInstantiatedSignature = cloneSignature(instantiatedSignature);
newInstantiatedSignature.resolvedReturnType = getOrCreateTypeFromSignature(newReturnSignature);
newInstantiatedSignature.resolvedReturnType = newReturnType;
return newInstantiatedSignature;
}
}
@ -16483,16 +16484,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
);
}
function getImplementationSignature(signature: Signature) {
return signature.typeParameters ?
signature.implementationSignatureCache ||= createImplementationSignature(signature) :
signature;
}
function createImplementationSignature(signature: Signature) {
return signature.typeParameters ? instantiateSignature(signature, createTypeMapper([], [])) : signature;
}
function getBaseSignature(signature: Signature) {
const typeParameters = signature.typeParameters;
if (typeParameters) {
@ -16514,7 +16505,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
return signature;
}
function getOrCreateTypeFromSignature(signature: Signature, outerTypeParameters?: TypeParameter[]): ObjectType {
function getOrCreateTypeFromSignature(signature: Signature): ObjectType {
// There are two ways to declare a construct signature, one is by declaring a class constructor
// using the constructor keyword, and the other is declaring a bare construct signature in an
// object type literal or interface (using the new keyword). Each way of declaring a constructor
@ -16525,16 +16516,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
// If declaration is undefined, it is likely to be the signature of the default constructor.
const isConstructor = kind === undefined || kind === SyntaxKind.Constructor || kind === SyntaxKind.ConstructSignature || kind === SyntaxKind.ConstructorType;
// The type must have a symbol with a `Function` flag and a declaration in order to be correctly flagged as possibly containing
// type variables by `couldContainTypeVariables`
const type = createObjectType(ObjectFlags.Anonymous | ObjectFlags.SingleSignatureType, createSymbol(SymbolFlags.Function, InternalSymbolName.Function)) as SingleSignatureType;
if (signature.declaration && !nodeIsSynthesized(signature.declaration)) { // skip synthetic declarations - keeping those around could be bad, since they lack a parent pointer
type.symbol.declarations = [signature.declaration];
type.symbol.valueDeclaration = signature.declaration;
}
outerTypeParameters ||= signature.declaration && getOuterTypeParameters(signature.declaration, /*includeThisTypes*/ true);
type.outerTypeParameters = outerTypeParameters;
const type = createObjectType(ObjectFlags.Anonymous | ObjectFlags.SingleSignatureType, signature.declaration?.symbol);
type.members = emptySymbols;
type.properties = emptyArray;
type.callSignatures = !isConstructor ? [signature] : emptyArray;
@ -20524,6 +20506,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
return createTypeMapper(map(forwardInferences, i => i.typeParameter), map(forwardInferences, () => unknownType));
}
/**
* Return a type mapper that combines the context's return mapper with a mapper that erases any additional type parameters
* to their inferences at the time of creation.
*/
function createOuterReturnMapper(context: InferenceContext) {
return context.outerReturnMapper ??= mergeTypeMappers(context.returnMapper, cloneInferenceContext(context).mapper);
}
function combineTypeMappers(mapper1: TypeMapper | undefined, mapper2: TypeMapper): TypeMapper {
return mapper1 ? makeCompositeTypeMapper(TypeMapKind.Composite, mapper1, mapper2) : mapper2;
}
@ -20620,7 +20610,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
const links = getNodeLinks(declaration);
const target = type.objectFlags & ObjectFlags.Reference ? links.resolvedType! as DeferredTypeReference :
type.objectFlags & ObjectFlags.Instantiated ? type.target! : type;
let typeParameters = type.objectFlags & ObjectFlags.SingleSignatureType ? (type as SingleSignatureType).outerTypeParameters : links.outerTypeParameters;
let typeParameters = links.outerTypeParameters;
if (!typeParameters) {
// The first time an anonymous type is instantiated we compute and store a list of the type
// parameters that are in scope (and therefore potentially referenced). For type literals that
@ -20646,19 +20636,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
const typeArguments = map(typeParameters, t => getMappedType(t, combinedMapper));
const newAliasSymbol = aliasSymbol || type.aliasSymbol;
const newAliasTypeArguments = aliasSymbol ? aliasTypeArguments : instantiateTypes(type.aliasTypeArguments, mapper);
const id = (type.objectFlags & ObjectFlags.SingleSignatureType ? "S" : "") + getTypeListId(typeArguments) + getAliasId(newAliasSymbol, newAliasTypeArguments);
const id = getTypeListId(typeArguments) + getAliasId(newAliasSymbol, newAliasTypeArguments);
if (!target.instantiations) {
target.instantiations = new Map<string, Type>();
target.instantiations.set(getTypeListId(typeParameters) + getAliasId(target.aliasSymbol, target.aliasTypeArguments), target);
}
let result = target.instantiations.get(id);
if (!result) {
if (type.objectFlags & ObjectFlags.SingleSignatureType) {
result = instantiateAnonymousType(type, mapper);
target.instantiations.set(id, result);
return result;
let newMapper = createTypeMapper(typeParameters, typeArguments);
if (target.objectFlags & ObjectFlags.SingleSignatureType && mapper) {
newMapper = combineTypeMappers(newMapper, mapper);
}
const newMapper = createTypeMapper(typeParameters, typeArguments);
result = target.objectFlags & ObjectFlags.Reference ? createDeferredTypeReference((type as DeferredTypeReference).target, (type as DeferredTypeReference).node, newMapper, newAliasSymbol, newAliasTypeArguments) :
target.objectFlags & ObjectFlags.Mapped ? instantiateMappedType(target as MappedType, newMapper, newAliasSymbol, newAliasTypeArguments) :
instantiateAnonymousType(target, newMapper, newAliasSymbol, newAliasTypeArguments);
@ -20856,9 +20844,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
if (type.objectFlags & ObjectFlags.InstantiationExpressionType) {
(result as InstantiationExpressionType).node = (type as InstantiationExpressionType).node;
}
if (type.objectFlags & ObjectFlags.SingleSignatureType) {
(result as SingleSignatureType).outerTypeParameters = (type as SingleSignatureType).outerTypeParameters;
}
result.target = type;
result.mapper = mapper;
result.aliasSymbol = aliasSymbol || type.aliasSymbol;
@ -26241,7 +26226,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
const result = !!(type.flags & TypeFlags.Instantiable ||
type.flags & TypeFlags.Object && !isNonGenericTopLevelType(type) && (
objectFlags & ObjectFlags.Reference && ((type as TypeReference).node || some(getTypeArguments(type as TypeReference), couldContainTypeVariables)) ||
objectFlags & ObjectFlags.SingleSignatureType && !!length((type as SingleSignatureType).outerTypeParameters) ||
objectFlags & ObjectFlags.Anonymous && type.symbol && type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.TypeLiteral | SymbolFlags.ObjectLiteral) && type.symbol.declarations ||
objectFlags & (ObjectFlags.Mapped | ObjectFlags.ReverseMapped | ObjectFlags.ObjectRestType | ObjectFlags.InstantiationExpressionType)
) ||
@ -26623,13 +26607,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
}
/**
* @returns `true` if `type` has the shape `[T[0]]` where `T` is `typeParameter`
*/
function isTupleOfSelf(typeParameter: TypeParameter, type: Type) {
return isTupleType(type) && getTupleElementType(type, 0) === getIndexedAccessType(typeParameter, getNumberLiteralType(0)) && !getTypeOfPropertyOfType(type, "1" as __String);
}
function inferTypes(inferences: InferenceInfo[], originalSource: Type, originalTarget: Type, priority = InferencePriority.None, contravariant = false) {
let bivariant = false;
let propagationType: Type;
@ -26758,11 +26735,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
inference.priority = priority;
}
if (priority === inference.priority) {
// Inferring A to [A[0]] is a zero information inference (it guarantees A becomes its constraint), but oft arises from generic argument list inferences
// By discarding it early, we can allow more fruitful results to be used instead.
if (isTupleOfSelf(inference.typeParameter, candidate)) {
return;
}
// We make contravariant inferences only if we are in a pure contravariant position,
// i.e. only if we have not descended into a bivariant position.
if (contravariant && !bivariant) {
@ -35718,8 +35690,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
// from the return type. We need a separate inference pass here because (a) instantiation of
// the source type uses the outer context's return mapper (which excludes inferences made from
// outer arguments), and (b) we don't want any further inferences going into this context.
// We use `createOuterReturnMapper` to ensure that all occurrences of outer type parameters are
// replaced with inferences produced from the outer return type or preceding outer arguments.
// This protects against circular inferences, i.e. avoiding situations where inferences reference
// type parameters for which the inferences are being made.
const returnContext = createInferenceContext(signature.typeParameters!, signature, context.flags);
const returnSourceType = instantiateType(contextualType, outerContext && outerContext.returnMapper);
const returnSourceType = instantiateType(contextualType, outerContext && createOuterReturnMapper(outerContext));
inferTypes(returnContext.inferences, returnSourceType, inferenceTargetType);
context.returnMapper = some(returnContext.inferences, hasInferenceCandidates) ? getMapperFromContext(cloneInferredPartOfContext(returnContext)) : undefined;
}
@ -35994,7 +35970,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
checkMode: CheckMode,
reportErrors: boolean,
containingMessageChain: (() => DiagnosticMessageChain | undefined) | undefined,
inferenceContext: InferenceContext | undefined,
): readonly Diagnostic[] | undefined {
const errorOutputContainer: ErrorOutputContainer = { errors: undefined, skipLogging: true };
if (isJsxCallLike(node)) {
@ -36029,10 +36004,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
// If one or more arguments are still excluded (as indicated by CheckMode.SkipContextSensitive),
// we obtain the regular type of any object literal arguments because we may not have inferred complete
// parameter types yet and therefore excess property checks may yield false positives (see #17041).
const regularArgType = checkMode & CheckMode.SkipContextSensitive ? getRegularTypeOfObjectLiteral(argType) : argType;
// If this was inferred under a given inference context, we may need to instantiate the expression type to finish resolving
// the type variables in the expression.
const checkArgType = inferenceContext ? instantiateType(regularArgType, inferenceContext.nonFixingMapper) : regularArgType;
const checkArgType = checkMode & CheckMode.SkipContextSensitive ? getRegularTypeOfObjectLiteral(argType) : argType;
const effectiveCheckArgumentNode = getEffectiveCheckNode(arg);
if (!checkTypeRelatedToAndOptionallyElaborate(checkArgType, paramType, relation, reportErrors ? effectiveCheckArgumentNode : undefined, effectiveCheckArgumentNode, headMessage, containingMessageChain, errorOutputContainer)) {
Debug.assert(!reportErrors || !!errorOutputContainer.errors, "parameter should have errors when reporting errors");
@ -36525,7 +36497,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
if (headMessage) {
chain = chainDiagnosticMessages(chain, headMessage);
}
const diags = getSignatureApplicabilityError(node, args, last, assignableRelation, CheckMode.Normal, /*reportErrors*/ true, () => chain, /*inferenceContext*/ undefined);
const diags = getSignatureApplicabilityError(node, args, last, assignableRelation, CheckMode.Normal, /*reportErrors*/ true, () => chain);
if (diags) {
for (const d of diags) {
if (last.declaration && candidatesForArgumentError.length > 3) {
@ -36547,7 +36519,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
let i = 0;
for (const c of candidatesForArgumentError) {
const chain = () => chainDiagnosticMessages(/*details*/ undefined, Diagnostics.Overload_0_of_1_2_gave_the_following_error, i + 1, candidates.length, signatureToString(c));
const diags = getSignatureApplicabilityError(node, args, c, assignableRelation, CheckMode.Normal, /*reportErrors*/ true, chain, /*inferenceContext*/ undefined);
const diags = getSignatureApplicabilityError(node, args, c, assignableRelation, CheckMode.Normal, /*reportErrors*/ true, chain);
if (diags) {
if (diags.length <= min) {
min = diags.length;
@ -36636,7 +36608,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
if (some(typeArguments) || !hasCorrectArity(node, args, candidate, signatureHelpTrailingComma)) {
return undefined;
}
if (getSignatureApplicabilityError(node, args, candidate, relation, CheckMode.Normal, /*reportErrors*/ false, /*containingMessageChain*/ undefined, /*inferenceContext*/ undefined)) {
if (getSignatureApplicabilityError(node, args, candidate, relation, CheckMode.Normal, /*reportErrors*/ false, /*containingMessageChain*/ undefined)) {
candidatesForArgumentError = [candidate];
return undefined;
}
@ -36644,7 +36616,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
for (let candidateIndex = 0; candidateIndex < candidates.length; candidateIndex++) {
let candidate = candidates[candidateIndex];
const candidate = candidates[candidateIndex];
if (!hasCorrectTypeArgumentArity(candidate, typeArguments) || !hasCorrectArity(node, args, candidate, signatureHelpTrailingComma)) {
continue;
}
@ -36653,14 +36625,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
let inferenceContext: InferenceContext | undefined;
if (candidate.typeParameters) {
// If we are *inside the body of candidate*, we need to create a clone of `candidate` with differing type parameter identities,
// so our inference results for this call doesn't pollute expression types referencing the outer type parameter!
const paramLocation = candidate.typeParameters[0].symbol.declarations?.[0]?.parent;
const candidateParameterContext = paramLocation || (candidate.declaration && isConstructorDeclaration(candidate.declaration) ? candidate.declaration.parent : candidate.declaration);
if (candidateParameterContext && findAncestor(node, a => a === candidateParameterContext)) {
candidate = getImplementationSignature(candidate);
}
let typeArgumentTypes: readonly Type[] | undefined;
let typeArgumentTypes: Type[] | undefined;
if (some(typeArguments)) {
typeArgumentTypes = checkTypeArguments(candidate, typeArguments, /*reportErrors*/ false);
if (!typeArgumentTypes) {
@ -36669,10 +36634,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
}
else {
inferenceContext = createInferenceContext(candidate.typeParameters!, candidate, /*flags*/ isInJSFile(node) ? InferenceFlags.AnyDefault : InferenceFlags.None);
// The resulting type arguments are instantiated with the inference context mapper, as the inferred types may still contain references to the inference context's
// type variables via contextual projection. These are kept generic until all inferences are locked in, so the dependencies expressed can pass constraint checks.
typeArgumentTypes = instantiateTypes(inferTypeArguments(node, candidate, args, argCheckMode | CheckMode.SkipGenericFunctions, inferenceContext), inferenceContext.nonFixingMapper);
inferenceContext = createInferenceContext(candidate.typeParameters, candidate, /*flags*/ isInJSFile(node) ? InferenceFlags.AnyDefault : InferenceFlags.None);
typeArgumentTypes = inferTypeArguments(node, candidate, args, argCheckMode | CheckMode.SkipGenericFunctions, inferenceContext);
argCheckMode |= inferenceContext.flags & InferenceFlags.SkippedGenericFunction ? CheckMode.SkipGenericFunctions : CheckMode.Normal;
}
checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, isInJSFile(candidate.declaration), inferenceContext && inferenceContext.inferredTypeParameters);
@ -36686,7 +36649,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
else {
checkCandidate = candidate;
}
if (getSignatureApplicabilityError(node, args, checkCandidate, relation, argCheckMode, /*reportErrors*/ false, /*containingMessageChain*/ undefined, inferenceContext)) {
if (getSignatureApplicabilityError(node, args, checkCandidate, relation, argCheckMode, /*reportErrors*/ false, /*containingMessageChain*/ undefined)) {
// Give preference to error candidates that have no rest parameters (as they are more specific)
(candidatesForArgumentError || (candidatesForArgumentError = [])).push(checkCandidate);
continue;
@ -36697,7 +36660,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
// round of type inference and applicability checking for this particular candidate.
argCheckMode = CheckMode.Normal;
if (inferenceContext) {
const typeArgumentTypes = instantiateTypes(inferTypeArguments(node, candidate, args, argCheckMode, inferenceContext), inferenceContext.mapper);
const typeArgumentTypes = inferTypeArguments(node, candidate, args, argCheckMode, inferenceContext);
checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, isInJSFile(candidate.declaration), inferenceContext.inferredTypeParameters);
// If the original signature has a generic rest type, instantiation may produce a
// signature with different arity and we need to perform another arity check.
@ -36706,7 +36669,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
continue;
}
}
if (getSignatureApplicabilityError(node, args, checkCandidate, relation, argCheckMode, /*reportErrors*/ false, /*containingMessageChain*/ undefined, inferenceContext)) {
if (getSignatureApplicabilityError(node, args, checkCandidate, relation, argCheckMode, /*reportErrors*/ false, /*containingMessageChain*/ undefined)) {
// Give preference to error candidates that have no rest parameters (as they are more specific)
(candidatesForArgumentError || (candidatesForArgumentError = [])).push(checkCandidate);
continue;
@ -41418,10 +41381,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
}
}
// TODO: The signature may reference any outer inference contexts, but we map pop off and then apply new inference contexts, and thus get different inferred types.
// That this is cached on the *first* such attempt is not currently an issue, since expression types *also* get cached on the first pass. If we ever properly speculate, though,
// the cached "isolatedSignatureType" signature field absolutely needs to be included in the list of speculative caches.
return getOrCreateTypeFromSignature(instantiateSignatureInContextOf(signature, contextualSignature, context), flatMap(inferenceContexts, c => c && map(c.inferences, i => i.typeParameter)).slice());
return getOrCreateTypeFromSignature(instantiateSignatureInContextOf(signature, contextualSignature, context));
}
}
}

View File

@ -6539,7 +6539,7 @@ export const enum ObjectFlags {
CouldContainTypeVariablesComputed = 1 << 19, // CouldContainTypeVariables flag has been computed
/** @internal */
CouldContainTypeVariables = 1 << 20, // Type could contain a type variable
SingleSignatureType = 1 << 27, // A single signature type extracted from a potentially broader type
ClassOrInterface = Class | Interface,
/** @internal */
RequiresWidening = ContainsWideningType | ContainsObjectOrArrayLiteral,
@ -6555,7 +6555,6 @@ export const enum ObjectFlags {
ContainsSpread = 1 << 21, // Object literal contains spread operation
ObjectRestType = 1 << 22, // Originates in object rest declaration
InstantiationExpressionType = 1 << 23, // Originates in instantiation expression
SingleSignatureType = 1 << 27, // A single signature type extracted from a potentially broader type
/** @internal */
IsClassInstanceClone = 1 << 24, // Type is a clone of a class instance type
// Flags that require TypeFlags.Object and ObjectFlags.Reference
@ -6770,12 +6769,6 @@ export interface AnonymousType extends ObjectType {
instantiations?: Map<string, Type>; // Instantiations of generic type alias (undefined if non-generic)
}
/** @internal */
// A SingleSignatureType may have bespoke outer type parameters to handle free type variable inferences
export interface SingleSignatureType extends AnonymousType {
outerTypeParameters?: TypeParameter[];
}
/** @internal */
export interface InstantiationExpressionType extends AnonymousType {
node: NodeWithTypeArguments;
@ -7061,8 +7054,6 @@ export interface Signature {
isolatedSignatureType?: ObjectType; // A manufactured type that just contains the signature for purposes of signature comparison
/** @internal */
instantiations?: Map<string, Signature>; // Generic signature instantiation cache
/** @internal */
implementationSignatureCache?: Signature; // Copy of the signature with fresh type parameters to use in checking the body of a potentially self-referential generic function (deferred)
}
export const enum IndexKind {
@ -7170,6 +7161,7 @@ export interface InferenceContext {
mapper: TypeMapper; // Mapper that fixes inferences
nonFixingMapper: TypeMapper; // Mapper that doesn't fix inferences
returnMapper?: TypeMapper; // Type mapper for inferences from return types (if any)
outerReturnMapper?: TypeMapper; // Type mapper for inferences from return types of outer function (if any)
inferredTypeParameters?: readonly TypeParameter[]; // Inferred type parameters for function result
intraExpressionInferenceSites?: IntraExpressionInferenceSite[];
}

View File

@ -6717,11 +6717,11 @@ declare namespace ts {
JSLiteral = 4096,
FreshLiteral = 8192,
ArrayLiteral = 16384,
SingleSignatureType = 134217728,
ClassOrInterface = 3,
ContainsSpread = 2097152,
ObjectRestType = 4194304,
InstantiationExpressionType = 8388608,
SingleSignatureType = 134217728,
}
interface ObjectType extends Type {
objectFlags: ObjectFlags;

View File

@ -0,0 +1,173 @@
//// [tests/cases/compiler/genericCallInferenceInConditionalTypes1.ts] ////
=== genericCallInferenceInConditionalTypes1.ts ===
// https://github.com/microsoft/TypeScript/issues/59937
type Ref<T> = {
>Ref : Symbol(Ref, Decl(genericCallInferenceInConditionalTypes1.ts, 0, 0))
>T : Symbol(T, Decl(genericCallInferenceInConditionalTypes1.ts, 2, 9))
current: T;
>current : Symbol(current, Decl(genericCallInferenceInConditionalTypes1.ts, 2, 15))
>T : Symbol(T, Decl(genericCallInferenceInConditionalTypes1.ts, 2, 9))
};
type FunctionComponent<P> = (props: P) => unknown;
>FunctionComponent : Symbol(FunctionComponent, Decl(genericCallInferenceInConditionalTypes1.ts, 4, 2))
>P : Symbol(P, Decl(genericCallInferenceInConditionalTypes1.ts, 6, 23))
>props : Symbol(props, Decl(genericCallInferenceInConditionalTypes1.ts, 6, 29))
>P : Symbol(P, Decl(genericCallInferenceInConditionalTypes1.ts, 6, 23))
type ComponentProps<T extends FunctionComponent<any>> =
>ComponentProps : Symbol(ComponentProps, Decl(genericCallInferenceInConditionalTypes1.ts, 6, 50))
>T : Symbol(T, Decl(genericCallInferenceInConditionalTypes1.ts, 8, 20))
>FunctionComponent : Symbol(FunctionComponent, Decl(genericCallInferenceInConditionalTypes1.ts, 4, 2))
T extends FunctionComponent<infer P> ? P : {};
>T : Symbol(T, Decl(genericCallInferenceInConditionalTypes1.ts, 8, 20))
>FunctionComponent : Symbol(FunctionComponent, Decl(genericCallInferenceInConditionalTypes1.ts, 4, 2))
>P : Symbol(P, Decl(genericCallInferenceInConditionalTypes1.ts, 9, 35))
>P : Symbol(P, Decl(genericCallInferenceInConditionalTypes1.ts, 9, 35))
type PropsWithoutRef<P> = P extends any
>PropsWithoutRef : Symbol(PropsWithoutRef, Decl(genericCallInferenceInConditionalTypes1.ts, 9, 48))
>P : Symbol(P, Decl(genericCallInferenceInConditionalTypes1.ts, 11, 21))
>P : Symbol(P, Decl(genericCallInferenceInConditionalTypes1.ts, 11, 21))
? "ref" extends keyof P
>P : Symbol(P, Decl(genericCallInferenceInConditionalTypes1.ts, 11, 21))
? Omit<P, "ref">
>Omit : Symbol(Omit, Decl(lib.es5.d.ts, --, --))
>P : Symbol(P, Decl(genericCallInferenceInConditionalTypes1.ts, 11, 21))
: P
>P : Symbol(P, Decl(genericCallInferenceInConditionalTypes1.ts, 11, 21))
: P;
>P : Symbol(P, Decl(genericCallInferenceInConditionalTypes1.ts, 11, 21))
type ComponentPropsWithoutRef<T extends FunctionComponent<any>> =
>ComponentPropsWithoutRef : Symbol(ComponentPropsWithoutRef, Decl(genericCallInferenceInConditionalTypes1.ts, 15, 6))
>T : Symbol(T, Decl(genericCallInferenceInConditionalTypes1.ts, 17, 30))
>FunctionComponent : Symbol(FunctionComponent, Decl(genericCallInferenceInConditionalTypes1.ts, 4, 2))
PropsWithoutRef<ComponentProps<T>>;
>PropsWithoutRef : Symbol(PropsWithoutRef, Decl(genericCallInferenceInConditionalTypes1.ts, 9, 48))
>ComponentProps : Symbol(ComponentProps, Decl(genericCallInferenceInConditionalTypes1.ts, 6, 50))
>T : Symbol(T, Decl(genericCallInferenceInConditionalTypes1.ts, 17, 30))
declare function forwardRef<T, P>(
>forwardRef : Symbol(forwardRef, Decl(genericCallInferenceInConditionalTypes1.ts, 18, 37))
>T : Symbol(T, Decl(genericCallInferenceInConditionalTypes1.ts, 20, 28))
>P : Symbol(P, Decl(genericCallInferenceInConditionalTypes1.ts, 20, 30))
component: (props: P, ref: Ref<T>) => unknown,
>component : Symbol(component, Decl(genericCallInferenceInConditionalTypes1.ts, 20, 34))
>props : Symbol(props, Decl(genericCallInferenceInConditionalTypes1.ts, 21, 14))
>P : Symbol(P, Decl(genericCallInferenceInConditionalTypes1.ts, 20, 30))
>ref : Symbol(ref, Decl(genericCallInferenceInConditionalTypes1.ts, 21, 23))
>Ref : Symbol(Ref, Decl(genericCallInferenceInConditionalTypes1.ts, 0, 0))
>T : Symbol(T, Decl(genericCallInferenceInConditionalTypes1.ts, 20, 28))
): (props: P & { ref?: Ref<T> }) => unknown;
>props : Symbol(props, Decl(genericCallInferenceInConditionalTypes1.ts, 22, 4))
>P : Symbol(P, Decl(genericCallInferenceInConditionalTypes1.ts, 20, 30))
>ref : Symbol(ref, Decl(genericCallInferenceInConditionalTypes1.ts, 22, 16))
>Ref : Symbol(Ref, Decl(genericCallInferenceInConditionalTypes1.ts, 0, 0))
>T : Symbol(T, Decl(genericCallInferenceInConditionalTypes1.ts, 20, 28))
const ComponentWithForwardRef = forwardRef(
>ComponentWithForwardRef : Symbol(ComponentWithForwardRef, Decl(genericCallInferenceInConditionalTypes1.ts, 24, 5))
>forwardRef : Symbol(forwardRef, Decl(genericCallInferenceInConditionalTypes1.ts, 18, 37))
<T extends FunctionComponent<any>>(
>T : Symbol(T, Decl(genericCallInferenceInConditionalTypes1.ts, 25, 3))
>FunctionComponent : Symbol(FunctionComponent, Decl(genericCallInferenceInConditionalTypes1.ts, 4, 2))
props: ComponentPropsWithoutRef<T>,
>props : Symbol(props, Decl(genericCallInferenceInConditionalTypes1.ts, 25, 37))
>ComponentPropsWithoutRef : Symbol(ComponentPropsWithoutRef, Decl(genericCallInferenceInConditionalTypes1.ts, 15, 6))
>T : Symbol(T, Decl(genericCallInferenceInConditionalTypes1.ts, 25, 3))
ref: Ref<HTMLElement>,
>ref : Symbol(ref, Decl(genericCallInferenceInConditionalTypes1.ts, 26, 39))
>Ref : Symbol(Ref, Decl(genericCallInferenceInConditionalTypes1.ts, 0, 0))
>HTMLElement : Symbol(HTMLElement, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
) => {
return null;
},
);
type Test<T> = T extends { component?: infer Component }
>Test : Symbol(Test, Decl(genericCallInferenceInConditionalTypes1.ts, 31, 2))
>T : Symbol(T, Decl(genericCallInferenceInConditionalTypes1.ts, 33, 10))
>T : Symbol(T, Decl(genericCallInferenceInConditionalTypes1.ts, 33, 10))
>component : Symbol(component, Decl(genericCallInferenceInConditionalTypes1.ts, 33, 26))
>Component : Symbol(Component, Decl(genericCallInferenceInConditionalTypes1.ts, 33, 44))
? Component extends FunctionComponent<any>
>Component : Symbol(Component, Decl(genericCallInferenceInConditionalTypes1.ts, 33, 44))
>FunctionComponent : Symbol(FunctionComponent, Decl(genericCallInferenceInConditionalTypes1.ts, 4, 2))
? ComponentProps<Component>
>ComponentProps : Symbol(ComponentProps, Decl(genericCallInferenceInConditionalTypes1.ts, 6, 50))
>Component : Symbol(Component, Decl(genericCallInferenceInConditionalTypes1.ts, 33, 44))
: never
: never;
// the first one here has a chance to pollute the cache
type Result1 = ComponentProps<typeof ComponentWithForwardRef>;
>Result1 : Symbol(Result1, Decl(genericCallInferenceInConditionalTypes1.ts, 37, 10))
>ComponentProps : Symbol(ComponentProps, Decl(genericCallInferenceInConditionalTypes1.ts, 6, 50))
>ComponentWithForwardRef : Symbol(ComponentWithForwardRef, Decl(genericCallInferenceInConditionalTypes1.ts, 24, 5))
// that could be incorrectly reused by this one
type Result2 = Test<{ component: typeof ComponentWithForwardRef }>; // no `T` leak
>Result2 : Symbol(Result2, Decl(genericCallInferenceInConditionalTypes1.ts, 40, 62))
>Test : Symbol(Test, Decl(genericCallInferenceInConditionalTypes1.ts, 31, 2))
>component : Symbol(component, Decl(genericCallInferenceInConditionalTypes1.ts, 42, 21))
>ComponentWithForwardRef : Symbol(ComponentWithForwardRef, Decl(genericCallInferenceInConditionalTypes1.ts, 24, 5))
// same as ComponentWithForwardRef above but using a resolved signature instead of a direct inferred result of `forwardRef`
declare const ComponentWithForwardRef2: <T extends FunctionComponent<any>>(
>ComponentWithForwardRef2 : Symbol(ComponentWithForwardRef2, Decl(genericCallInferenceInConditionalTypes1.ts, 45, 13))
>T : Symbol(T, Decl(genericCallInferenceInConditionalTypes1.ts, 45, 41))
>FunctionComponent : Symbol(FunctionComponent, Decl(genericCallInferenceInConditionalTypes1.ts, 4, 2))
props: PropsWithoutRef<ComponentProps<T>> & {
>props : Symbol(props, Decl(genericCallInferenceInConditionalTypes1.ts, 45, 75))
>PropsWithoutRef : Symbol(PropsWithoutRef, Decl(genericCallInferenceInConditionalTypes1.ts, 9, 48))
>ComponentProps : Symbol(ComponentProps, Decl(genericCallInferenceInConditionalTypes1.ts, 6, 50))
>T : Symbol(T, Decl(genericCallInferenceInConditionalTypes1.ts, 45, 41))
className?: string;
>className : Symbol(className, Decl(genericCallInferenceInConditionalTypes1.ts, 46, 47))
as?: T | undefined;
>as : Symbol(as, Decl(genericCallInferenceInConditionalTypes1.ts, 47, 23))
>T : Symbol(T, Decl(genericCallInferenceInConditionalTypes1.ts, 45, 41))
} & {
ref?: Ref<HTMLElement> | undefined;
>ref : Symbol(ref, Decl(genericCallInferenceInConditionalTypes1.ts, 49, 7))
>Ref : Symbol(Ref, Decl(genericCallInferenceInConditionalTypes1.ts, 0, 0))
>HTMLElement : Symbol(HTMLElement, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
},
) => unknown;
type Result3 = ComponentProps<typeof ComponentWithForwardRef2>;
>Result3 : Symbol(Result3, Decl(genericCallInferenceInConditionalTypes1.ts, 52, 13))
>ComponentProps : Symbol(ComponentProps, Decl(genericCallInferenceInConditionalTypes1.ts, 6, 50))
>ComponentWithForwardRef2 : Symbol(ComponentWithForwardRef2, Decl(genericCallInferenceInConditionalTypes1.ts, 45, 13))
type Result4 = Test<{ component: typeof ComponentWithForwardRef2 }>;
>Result4 : Symbol(Result4, Decl(genericCallInferenceInConditionalTypes1.ts, 54, 63))
>Test : Symbol(Test, Decl(genericCallInferenceInConditionalTypes1.ts, 31, 2))
>component : Symbol(component, Decl(genericCallInferenceInConditionalTypes1.ts, 55, 21))
>ComponentWithForwardRef2 : Symbol(ComponentWithForwardRef2, Decl(genericCallInferenceInConditionalTypes1.ts, 45, 13))

View File

@ -0,0 +1,151 @@
//// [tests/cases/compiler/genericCallInferenceInConditionalTypes1.ts] ////
=== genericCallInferenceInConditionalTypes1.ts ===
// https://github.com/microsoft/TypeScript/issues/59937
type Ref<T> = {
>Ref : Ref<T>
> : ^^^^^^
current: T;
>current : T
> : ^
};
type FunctionComponent<P> = (props: P) => unknown;
>FunctionComponent : FunctionComponent<P>
> : ^^^^^^^^^^^^^^^^^^^^
>props : P
> : ^
type ComponentProps<T extends FunctionComponent<any>> =
>ComponentProps : ComponentProps<T>
> : ^^^^^^^^^^^^^^^^^
T extends FunctionComponent<infer P> ? P : {};
type PropsWithoutRef<P> = P extends any
>PropsWithoutRef : PropsWithoutRef<P>
> : ^^^^^^^^^^^^^^^^^^
? "ref" extends keyof P
? Omit<P, "ref">
: P
: P;
type ComponentPropsWithoutRef<T extends FunctionComponent<any>> =
>ComponentPropsWithoutRef : ComponentPropsWithoutRef<T>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^
PropsWithoutRef<ComponentProps<T>>;
declare function forwardRef<T, P>(
>forwardRef : <T, P>(component: (props: P, ref: Ref<T>) => unknown) => (props: P & { ref?: Ref<T>; }) => unknown
> : ^ ^^ ^^ ^^ ^^^^^
component: (props: P, ref: Ref<T>) => unknown,
>component : (props: P, ref: Ref<T>) => unknown
> : ^ ^^ ^^ ^^ ^^^^^
>props : P
> : ^
>ref : Ref<T>
> : ^^^^^^
): (props: P & { ref?: Ref<T> }) => unknown;
>props : P & { ref?: Ref<T>; }
> : ^^^^^^^^^^^^ ^^^
>ref : Ref<T> | undefined
> : ^^^^^^^^^^^^^^^^^^
const ComponentWithForwardRef = forwardRef(
>ComponentWithForwardRef : <T extends FunctionComponent<any>>(props: PropsWithoutRef<ComponentProps<T>> & { ref?: Ref<HTMLElement> | undefined; }) => unknown
> : ^ ^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>forwardRef( <T extends FunctionComponent<any>>( props: ComponentPropsWithoutRef<T>, ref: Ref<HTMLElement>, ) => { return null; },) : <T extends FunctionComponent<any>>(props: PropsWithoutRef<ComponentProps<T>> & { ref?: Ref<HTMLElement> | undefined; }) => unknown
> : ^ ^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>forwardRef : <T, P>(component: (props: P, ref: Ref<T>) => unknown) => (props: P & { ref?: Ref<T>; }) => unknown
> : ^ ^^ ^^ ^^ ^^^^^
<T extends FunctionComponent<any>>(
><T extends FunctionComponent<any>>( props: ComponentPropsWithoutRef<T>, ref: Ref<HTMLElement>, ) => { return null; } : <T extends FunctionComponent<any>>(props: ComponentPropsWithoutRef<T>, ref: Ref<HTMLElement>) => null
> : ^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^^^^^
props: ComponentPropsWithoutRef<T>,
>props : PropsWithoutRef<ComponentProps<T>>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ref: Ref<HTMLElement>,
>ref : Ref<HTMLElement>
> : ^^^^^^^^^^^^^^^^
) => {
return null;
},
);
type Test<T> = T extends { component?: infer Component }
>Test : Test<T>
> : ^^^^^^^
>component : Component | undefined
> : ^^^^^^^^^^^^^^^^^^^^^
? Component extends FunctionComponent<any>
? ComponentProps<Component>
: never
: never;
// the first one here has a chance to pollute the cache
type Result1 = ComponentProps<typeof ComponentWithForwardRef>;
>Result1 : Omit<any, "ref"> & { ref?: Ref<HTMLElement> | undefined; }
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>ComponentWithForwardRef : <T extends FunctionComponent<any>>(props: PropsWithoutRef<ComponentProps<T>> & { ref?: Ref<HTMLElement> | undefined; }) => unknown
> : ^ ^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// that could be incorrectly reused by this one
type Result2 = Test<{ component: typeof ComponentWithForwardRef }>; // no `T` leak
>Result2 : Omit<any, "ref"> & { ref?: Ref<HTMLElement> | undefined; }
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>component : <T extends FunctionComponent<any>>(props: PropsWithoutRef<ComponentProps<T>> & { ref?: Ref<HTMLElement> | undefined; }) => unknown
> : ^ ^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>ComponentWithForwardRef : <T extends FunctionComponent<any>>(props: PropsWithoutRef<ComponentProps<T>> & { ref?: Ref<HTMLElement> | undefined; }) => unknown
> : ^ ^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// same as ComponentWithForwardRef above but using a resolved signature instead of a direct inferred result of `forwardRef`
declare const ComponentWithForwardRef2: <T extends FunctionComponent<any>>(
>ComponentWithForwardRef2 : <T extends FunctionComponent<any>>(props: PropsWithoutRef<ComponentProps<T>> & { className?: string; as?: T | undefined; } & { ref?: Ref<HTMLElement> | undefined; }) => unknown
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
props: PropsWithoutRef<ComponentProps<T>> & {
>props : PropsWithoutRef<ComponentProps<T>> & { className?: string; as?: T | undefined; } & { ref?: Ref<HTMLElement> | undefined; }
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^ ^^^^^^^^^^^^^^ ^^^
className?: string;
>className : string | undefined
> : ^^^^^^^^^^^^^^^^^^
as?: T | undefined;
>as : T | undefined
> : ^^^^^^^^^^^^^
} & {
ref?: Ref<HTMLElement> | undefined;
>ref : Ref<HTMLElement> | undefined
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
},
) => unknown;
type Result3 = ComponentProps<typeof ComponentWithForwardRef2>;
>Result3 : Omit<any, "ref"> & { className?: string; as?: FunctionComponent<any> | undefined; } & { ref?: Ref<HTMLElement> | undefined; }
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^
>ComponentWithForwardRef2 : <T extends FunctionComponent<any>>(props: PropsWithoutRef<ComponentProps<T>> & { className?: string; as?: T | undefined; } & { ref?: Ref<HTMLElement> | undefined; }) => unknown
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
type Result4 = Test<{ component: typeof ComponentWithForwardRef2 }>;
>Result4 : Omit<any, "ref"> & { className?: string; as?: FunctionComponent<any> | undefined; } & { ref?: Ref<HTMLElement> | undefined; }
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^
>component : <T extends FunctionComponent<any>>(props: PropsWithoutRef<ComponentProps<T>> & { className?: string; as?: T | undefined; } & { ref?: Ref<HTMLElement> | undefined; }) => unknown
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
>ComponentWithForwardRef2 : <T extends FunctionComponent<any>>(props: PropsWithoutRef<ComponentProps<T>> & { className?: string; as?: T | undefined; } & { ref?: Ref<HTMLElement> | undefined; }) => unknown
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^

View File

@ -0,0 +1,168 @@
//// [tests/cases/compiler/genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts] ////
=== genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts ===
declare const EffectTypeId: unique symbol;
>EffectTypeId : Symbol(EffectTypeId, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 0, 13))
interface Variance<out A, out E, out R> {
>Variance : Symbol(Variance, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 0, 42))
>A : Symbol(A, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 2, 19))
>E : Symbol(E, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 2, 25))
>R : Symbol(R, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 2, 32))
readonly [EffectTypeId]: VarianceStruct<A, E, R>;
>[EffectTypeId] : Symbol(Variance[EffectTypeId], Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 2, 41))
>EffectTypeId : Symbol(EffectTypeId, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 0, 13))
>VarianceStruct : Symbol(VarianceStruct, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 6, 36))
>A : Symbol(A, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 2, 19))
>E : Symbol(E, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 2, 25))
>R : Symbol(R, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 2, 32))
}
type Covariant<A> = (_: never) => A;
>Covariant : Symbol(Covariant, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 4, 1))
>A : Symbol(A, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 6, 15))
>_ : Symbol(_, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 6, 21))
>A : Symbol(A, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 6, 15))
interface VarianceStruct<out A, out E, out R> {
>VarianceStruct : Symbol(VarianceStruct, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 6, 36))
>A : Symbol(A, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 8, 25))
>E : Symbol(E, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 8, 31))
>R : Symbol(R, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 8, 38))
readonly _V: string;
>_V : Symbol(VarianceStruct._V, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 8, 47))
readonly _A: Covariant<A>;
>_A : Symbol(VarianceStruct._A, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 9, 22))
>Covariant : Symbol(Covariant, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 4, 1))
>A : Symbol(A, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 8, 25))
readonly _E: Covariant<E>;
>_E : Symbol(VarianceStruct._E, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 10, 28))
>Covariant : Symbol(Covariant, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 4, 1))
>E : Symbol(E, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 8, 31))
readonly _R: Covariant<R>;
>_R : Symbol(VarianceStruct._R, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 11, 28))
>Covariant : Symbol(Covariant, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 4, 1))
>R : Symbol(R, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 8, 38))
}
interface Effect<out A, out E = never, out R = never>
>Effect : Symbol(Effect, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 13, 1))
>A : Symbol(A, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 15, 17))
>E : Symbol(E, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 15, 23))
>R : Symbol(R, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 15, 38))
extends Variance<A, E, R> {}
>Variance : Symbol(Variance, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 0, 42))
>A : Symbol(A, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 15, 17))
>E : Symbol(E, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 15, 23))
>R : Symbol(R, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 15, 38))
declare const succeed: <A>(value: A) => Effect<A>;
>succeed : Symbol(succeed, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 18, 13))
>A : Symbol(A, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 18, 24))
>value : Symbol(value, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 18, 27))
>A : Symbol(A, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 18, 24))
>Effect : Symbol(Effect, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 13, 1))
>A : Symbol(A, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 18, 24))
type F<X, Y> = Y extends { _type: infer Z }
>F : Symbol(F, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 18, 50))
>X : Symbol(X, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 20, 7))
>Y : Symbol(Y, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 20, 9))
>Y : Symbol(Y, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 20, 9))
>_type : Symbol(_type, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 20, 26))
>Z : Symbol(Z, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 20, 39))
? X extends Effect<infer A, infer E, infer R>
>X : Symbol(X, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 20, 7))
>Effect : Symbol(Effect, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 13, 1))
>A : Symbol(A, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 21, 26))
>E : Symbol(E, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 21, 35))
>R : Symbol(R, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 21, 44))
? Effect<A, E, R | Z>
>Effect : Symbol(Effect, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 13, 1))
>A : Symbol(A, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 21, 26))
>E : Symbol(E, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 21, 35))
>R : Symbol(R, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 21, 44))
>Z : Symbol(Z, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 20, 39))
: X
>X : Symbol(X, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 20, 7))
: X;
>X : Symbol(X, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 20, 7))
type ProxyMap<Service> = {
>ProxyMap : Symbol(ProxyMap, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 24, 6))
>Service : Symbol(Service, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 26, 14))
[K in keyof Service]: (Service & { _type: Service })[K];
>K : Symbol(K, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 27, 3))
>Service : Symbol(Service, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 26, 14))
>Service : Symbol(Service, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 26, 14))
>_type : Symbol(_type, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 27, 36))
>Service : Symbol(Service, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 26, 14))
>K : Symbol(K, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 27, 3))
};
declare const implement: <T>() => <I extends ReadonlyArray<any>, X>(
>implement : Symbol(implement, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 30, 13))
>T : Symbol(T, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 30, 26))
>I : Symbol(I, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 30, 35))
>ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.es5.d.ts, --, --))
>X : Symbol(X, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 30, 64))
x: (...i: I) => X,
>x : Symbol(x, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 30, 68))
>i : Symbol(i, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 31, 6))
>I : Symbol(I, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 30, 35))
>X : Symbol(X, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 30, 64))
) => (...i: I) => F<X, T>;
>i : Symbol(i, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 32, 6))
>I : Symbol(I, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 30, 35))
>F : Symbol(F, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 18, 50))
>X : Symbol(X, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 30, 64))
>T : Symbol(T, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 30, 26))
class XXX {
>XXX : Symbol(XXX, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 32, 26))
log = implement<this>()(<N extends number>(n: N) => succeed(n));
>log : Symbol(XXX.log, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 34, 11))
>implement : Symbol(implement, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 30, 13))
>N : Symbol(N, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 35, 27))
>n : Symbol(n, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 35, 45))
>N : Symbol(N, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 35, 27))
>succeed : Symbol(succeed, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 18, 13))
>n : Symbol(n, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 35, 45))
}
export declare const inner: XXX;
>inner : Symbol(inner, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 38, 20))
>XXX : Symbol(XXX, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 32, 26))
export declare const outer: ProxyMap<XXX>;
>outer : Symbol(outer, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 39, 20))
>ProxyMap : Symbol(ProxyMap, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 24, 6))
>XXX : Symbol(XXX, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 32, 26))
export const a = inner.log(100); // Effect<100, never, never>
>a : Symbol(a, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 41, 12))
>inner.log : Symbol(XXX.log, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 34, 11))
>inner : Symbol(inner, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 38, 20))
>log : Symbol(XXX.log, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 34, 11))
export const b = outer.log(100); // Effect<100, never, XXX>
>b : Symbol(b, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 42, 12))
>outer.log : Symbol(log, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 34, 11))
>outer : Symbol(outer, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 39, 20))
>log : Symbol(log, Decl(genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts, 34, 11))

View File

@ -0,0 +1,144 @@
//// [tests/cases/compiler/genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts] ////
=== genericCallInferenceUsingThisTypeNoInvalidCacheReuseAfterMappedTypeApplication1.ts ===
declare const EffectTypeId: unique symbol;
>EffectTypeId : unique symbol
> : ^^^^^^^^^^^^^
interface Variance<out A, out E, out R> {
readonly [EffectTypeId]: VarianceStruct<A, E, R>;
>[EffectTypeId] : VarianceStruct<A, E, R>
> : ^^^^^^^^^^^^^^^^^^^^^^^
>EffectTypeId : unique symbol
> : ^^^^^^^^^^^^^
}
type Covariant<A> = (_: never) => A;
>Covariant : Covariant<A>
> : ^^^^^^^^^^^^
>_ : never
> : ^^^^^
interface VarianceStruct<out A, out E, out R> {
readonly _V: string;
>_V : string
> : ^^^^^^
readonly _A: Covariant<A>;
>_A : Covariant<A>
> : ^^^^^^^^^^^^
readonly _E: Covariant<E>;
>_E : Covariant<E>
> : ^^^^^^^^^^^^
readonly _R: Covariant<R>;
>_R : Covariant<R>
> : ^^^^^^^^^^^^
}
interface Effect<out A, out E = never, out R = never>
extends Variance<A, E, R> {}
declare const succeed: <A>(value: A) => Effect<A>;
>succeed : <A>(value: A) => Effect<A>
> : ^ ^^ ^^ ^^^^^
>value : A
> : ^
type F<X, Y> = Y extends { _type: infer Z }
>F : F<X, Y>
> : ^^^^^^^
>_type : Z
> : ^
? X extends Effect<infer A, infer E, infer R>
? Effect<A, E, R | Z>
: X
: X;
type ProxyMap<Service> = {
>ProxyMap : ProxyMap<Service>
> : ^^^^^^^^^^^^^^^^^
[K in keyof Service]: (Service & { _type: Service })[K];
>_type : Service
> : ^^^^^^^
};
declare const implement: <T>() => <I extends ReadonlyArray<any>, X>(
>implement : <T>() => <I extends ReadonlyArray<any>, X>(x: (...i: I) => X) => (...i: I) => F<X, T>
> : ^ ^^^^^^^
x: (...i: I) => X,
>x : (...i: I) => X
> : ^^^^ ^^ ^^^^^
>i : I
> : ^
) => (...i: I) => F<X, T>;
>i : I
> : ^
class XXX {
>XXX : XXX
> : ^^^
log = implement<this>()(<N extends number>(n: N) => succeed(n));
>log : <N extends number>(n: N) => F<Effect<N, never, never>, this>
> : ^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>implement<this>()(<N extends number>(n: N) => succeed(n)) : <N extends number>(n: N) => F<Effect<N, never, never>, this>
> : ^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>implement<this>() : <I extends ReadonlyArray<any>, X>(x: (...i: I) => X) => (...i: I) => F<X, this>
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^^ ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^
>implement : <T>() => <I extends ReadonlyArray<any>, X>(x: (...i: I) => X) => (...i: I) => F<X, T>
> : ^ ^^^^^^^
><N extends number>(n: N) => succeed(n) : <N extends number>(n: N) => Effect<N, never, never>
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>n : N
> : ^
>succeed(n) : Effect<N, never, never>
> : ^^^^^^^^^^^^^^^^^^^^^^^
>succeed : <A>(value: A) => Effect<A>
> : ^ ^^ ^^ ^^^^^
>n : N
> : ^
}
export declare const inner: XXX;
>inner : XXX
> : ^^^
export declare const outer: ProxyMap<XXX>;
>outer : ProxyMap<XXX>
> : ^^^^^^^^^^^^^
export const a = inner.log(100); // Effect<100, never, never>
>a : F<Effect<100, never, never>, this>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>inner.log(100) : F<Effect<100, never, never>, this>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>inner.log : <N extends number>(n: N) => F<Effect<N, never, never>, this>
> : ^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>inner : XXX
> : ^^^
>log : <N extends number>(n: N) => F<Effect<N, never, never>, this>
> : ^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>100 : 100
> : ^^^
export const b = outer.log(100); // Effect<100, never, XXX>
>b : F<Effect<100, never, never>, this>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>outer.log(100) : F<Effect<100, never, never>, this>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>outer.log : <N extends number>(n: N) => F<Effect<N, never, never>, this>
> : ^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>outer : ProxyMap<XXX>
> : ^^^^^^^^^^^^^
>log : <N extends number>(n: N) => F<Effect<N, never, never>, this>
> : ^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>100 : 100
> : ^^^

View File

@ -42,3 +42,60 @@ const added2 = addP2({ bar: 2 });
>addP2 : Symbol(addP2, Decl(genericCallInferenceWithGenericLocalFunction.ts, 9, 5))
>bar : Symbol(bar, Decl(genericCallInferenceWithGenericLocalFunction.ts, 10, 22))
function withP3<P>(p: P) {
>withP3 : Symbol(withP3, Decl(genericCallInferenceWithGenericLocalFunction.ts, 10, 33))
>P : Symbol(P, Decl(genericCallInferenceWithGenericLocalFunction.ts, 12, 16))
>p : Symbol(p, Decl(genericCallInferenceWithGenericLocalFunction.ts, 12, 19))
>P : Symbol(P, Decl(genericCallInferenceWithGenericLocalFunction.ts, 12, 16))
const m =
>m : Symbol(m, Decl(genericCallInferenceWithGenericLocalFunction.ts, 13, 7))
<I,>(from: I) =>
>I : Symbol(I, Decl(genericCallInferenceWithGenericLocalFunction.ts, 14, 5))
>from : Symbol(from, Decl(genericCallInferenceWithGenericLocalFunction.ts, 14, 9))
>I : Symbol(I, Decl(genericCallInferenceWithGenericLocalFunction.ts, 14, 5))
<I2,>(from2: I2) => ({ ...from, ...from2, ...p });
>I2 : Symbol(I2, Decl(genericCallInferenceWithGenericLocalFunction.ts, 15, 5))
>from2 : Symbol(from2, Decl(genericCallInferenceWithGenericLocalFunction.ts, 15, 10))
>I2 : Symbol(I2, Decl(genericCallInferenceWithGenericLocalFunction.ts, 15, 5))
>from : Symbol(from, Decl(genericCallInferenceWithGenericLocalFunction.ts, 14, 9))
>from2 : Symbol(from2, Decl(genericCallInferenceWithGenericLocalFunction.ts, 15, 10))
>p : Symbol(p, Decl(genericCallInferenceWithGenericLocalFunction.ts, 12, 19))
return createTransform(m);
>createTransform : Symbol(createTransform, Decl(genericCallInferenceWithGenericLocalFunction.ts, 2, 5))
>m : Symbol(m, Decl(genericCallInferenceWithGenericLocalFunction.ts, 13, 7))
}
const addP3 = withP3({ a: 1 });
>addP3 : Symbol(addP3, Decl(genericCallInferenceWithGenericLocalFunction.ts, 19, 5))
>withP3 : Symbol(withP3, Decl(genericCallInferenceWithGenericLocalFunction.ts, 10, 33))
>a : Symbol(a, Decl(genericCallInferenceWithGenericLocalFunction.ts, 19, 22))
const addedSome3 = addP3({ b: '' });
>addedSome3 : Symbol(addedSome3, Decl(genericCallInferenceWithGenericLocalFunction.ts, 20, 5))
>addP3 : Symbol(addP3, Decl(genericCallInferenceWithGenericLocalFunction.ts, 19, 5))
>b : Symbol(b, Decl(genericCallInferenceWithGenericLocalFunction.ts, 20, 26))
const added3 = addedSome3({ c: true });
>added3 : Symbol(added3, Decl(genericCallInferenceWithGenericLocalFunction.ts, 21, 5))
>addedSome3 : Symbol(addedSome3, Decl(genericCallInferenceWithGenericLocalFunction.ts, 20, 5))
>c : Symbol(c, Decl(genericCallInferenceWithGenericLocalFunction.ts, 21, 27))
const addP3_other = withP3({ foo: 'bar' });
>addP3_other : Symbol(addP3_other, Decl(genericCallInferenceWithGenericLocalFunction.ts, 23, 5))
>withP3 : Symbol(withP3, Decl(genericCallInferenceWithGenericLocalFunction.ts, 10, 33))
>foo : Symbol(foo, Decl(genericCallInferenceWithGenericLocalFunction.ts, 23, 28))
const addedSome3_other = addP3_other({ qwerty: 123 });
>addedSome3_other : Symbol(addedSome3_other, Decl(genericCallInferenceWithGenericLocalFunction.ts, 24, 5))
>addP3_other : Symbol(addP3_other, Decl(genericCallInferenceWithGenericLocalFunction.ts, 23, 5))
>qwerty : Symbol(qwerty, Decl(genericCallInferenceWithGenericLocalFunction.ts, 24, 38))
const added3_other = addedSome3_other({ bazinga: true });
>added3_other : Symbol(added3_other, Decl(genericCallInferenceWithGenericLocalFunction.ts, 25, 5))
>addedSome3_other : Symbol(addedSome3_other, Decl(genericCallInferenceWithGenericLocalFunction.ts, 24, 5))
>bazinga : Symbol(bazinga, Decl(genericCallInferenceWithGenericLocalFunction.ts, 25, 39))

View File

@ -74,3 +74,128 @@ const added2 = addP2({ bar: 2 });
>2 : 2
> : ^
function withP3<P>(p: P) {
>withP3 : <P>(p: P) => <I>(from: I) => <I2>(from2: I2) => I & I2 & P
> : ^ ^^ ^^ ^^^^^^ ^^ ^^^^^^^^^ ^^ ^^ ^^^^^^^^^^^^^^^
>p : P
> : ^
const m =
>m : <I>(from: I) => <I2>(from2: I2) => I & I2 & P
> : ^ ^^ ^^ ^^^^^^ ^^ ^^^^^^^^^^^^^^^
<I,>(from: I) =>
><I,>(from: I) => <I2,>(from2: I2) => ({ ...from, ...from2, ...p }) : <I>(from: I) => <I2>(from2: I2) => I & I2 & P
> : ^ ^^ ^^ ^^^^^^ ^^ ^^^^^^^^^^^^^^^
>from : I
> : ^
<I2,>(from2: I2) => ({ ...from, ...from2, ...p });
><I2,>(from2: I2) => ({ ...from, ...from2, ...p }) : <I2>(from2: I2) => I & I2 & P
> : ^ ^^ ^^ ^^^^^^^^^^^^^^^
>from2 : I2
> : ^^
>({ ...from, ...from2, ...p }) : I & I2 & P
> : ^^^^^^^^^^
>{ ...from, ...from2, ...p } : I & I2 & P
> : ^^^^^^^^^^
>from : I
> : ^
>from2 : I2
> : ^^
>p : P
> : ^
return createTransform(m);
>createTransform(m) : <I>(from: I) => <I2>(from2: I2) => I & I2 & P
> : ^ ^^ ^^^^^^^^^ ^^ ^^ ^^^^^^^^^^^^^^^
>createTransform : <I, O>(tr: (from: I) => O) => (from: I) => O
> : ^ ^^ ^^ ^^ ^^^^^^ ^^ ^^^^^
>m : <I>(from: I) => <I2>(from2: I2) => I & I2 & P
> : ^ ^^ ^^ ^^^^^^ ^^ ^^^^^^^^^^^^^^^
}
const addP3 = withP3({ a: 1 });
>addP3 : <I>(from: I) => <I2>(from2: I2) => I & I2 & { a: number; }
> : ^ ^^ ^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>withP3({ a: 1 }) : <I>(from: I) => <I2>(from2: I2) => I & I2 & { a: number; }
> : ^ ^^ ^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>withP3 : <P>(p: P) => <I>(from: I) => <I2>(from2: I2) => I & I2 & P
> : ^ ^^ ^^ ^^^^^^ ^^ ^^^^^^^^^ ^^ ^^ ^^^^^^^^^^^^^^^
>{ a: 1 } : { a: number; }
> : ^^^^^^^^^^^^^^
>a : number
> : ^^^^^^
>1 : 1
> : ^
const addedSome3 = addP3({ b: '' });
>addedSome3 : <I2>(from2: I2) => { b: string; } & I2 & { a: number; }
> : ^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>addP3({ b: '' }) : <I2>(from2: I2) => { b: string; } & I2 & { a: number; }
> : ^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>addP3 : <I>(from: I) => <I2>(from2: I2) => I & I2 & { a: number; }
> : ^ ^^ ^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>{ b: '' } : { b: string; }
> : ^^^^^^^^^^^^^^
>b : string
> : ^^^^^^
>'' : ""
> : ^^
const added3 = addedSome3({ c: true });
>added3 : { b: string; } & { c: boolean; } & { a: number; }
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>addedSome3({ c: true }) : { b: string; } & { c: boolean; } & { a: number; }
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>addedSome3 : <I2>(from2: I2) => { b: string; } & I2 & { a: number; }
> : ^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>{ c: true } : { c: true; }
> : ^^^^^^^^^^^^
>c : true
> : ^^^^
>true : true
> : ^^^^
const addP3_other = withP3({ foo: 'bar' });
>addP3_other : <I>(from: I) => <I2>(from2: I2) => I & I2 & { foo: string; }
> : ^ ^^ ^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>withP3({ foo: 'bar' }) : <I>(from: I) => <I2>(from2: I2) => I & I2 & { foo: string; }
> : ^ ^^ ^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>withP3 : <P>(p: P) => <I>(from: I) => <I2>(from2: I2) => I & I2 & P
> : ^ ^^ ^^ ^^^^^^ ^^ ^^^^^^^^^ ^^ ^^ ^^^^^^^^^^^^^^^
>{ foo: 'bar' } : { foo: string; }
> : ^^^^^^^^^^^^^^^^
>foo : string
> : ^^^^^^
>'bar' : "bar"
> : ^^^^^
const addedSome3_other = addP3_other({ qwerty: 123 });
>addedSome3_other : <I2>(from2: I2) => { qwerty: number; } & I2 & { foo: string; }
> : ^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>addP3_other({ qwerty: 123 }) : <I2>(from2: I2) => { qwerty: number; } & I2 & { foo: string; }
> : ^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>addP3_other : <I>(from: I) => <I2>(from2: I2) => I & I2 & { foo: string; }
> : ^ ^^ ^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>{ qwerty: 123 } : { qwerty: number; }
> : ^^^^^^^^^^^^^^^^^^^
>qwerty : number
> : ^^^^^^
>123 : 123
> : ^^^
const added3_other = addedSome3_other({ bazinga: true });
>added3_other : { qwerty: number; } & { bazinga: boolean; } & { foo: string; }
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>addedSome3_other({ bazinga: true }) : { qwerty: number; } & { bazinga: boolean; } & { foo: string; }
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>addedSome3_other : <I2>(from2: I2) => { qwerty: number; } & I2 & { foo: string; }
> : ^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>{ bazinga: true } : { bazinga: true; }
> : ^^^^^^^^^^^^^^^^^^
>bazinga : true
> : ^^^^
>true : true
> : ^^^^

View File

@ -2,7 +2,7 @@
=== Performance Stats ===
Type Count: 1,000
Instantiation count: 2,500
Instantiation count: 1,000
=== genericFunctionInference1.ts ===
declare function pipe<A extends any[], B>(ab: (...args: A) => B): (...args: A) => B;

View File

@ -0,0 +1,14 @@
inferenceFromGenericClassNoCrash1.ts(5,3): error TS2564: Property 't' has no initializer and is not definitely assigned in the constructor.
==== inferenceFromGenericClassNoCrash1.ts (1 errors) ====
// https://github.com/microsoft/TypeScript/issues/61633#issuecomment-2841778576
function RenderFlagsMixin<T extends new (...args: any[]) => object>(Base?: T) {}
class Container<T> {
t: T;
~
!!! error TS2564: Property 't' has no initializer and is not definitely assigned in the constructor.
}
RenderFlagsMixin(Container);

View File

@ -0,0 +1,24 @@
//// [tests/cases/compiler/inferenceFromGenericClassNoCrash1.ts] ////
=== inferenceFromGenericClassNoCrash1.ts ===
// https://github.com/microsoft/TypeScript/issues/61633#issuecomment-2841778576
function RenderFlagsMixin<T extends new (...args: any[]) => object>(Base?: T) {}
>RenderFlagsMixin : Symbol(RenderFlagsMixin, Decl(inferenceFromGenericClassNoCrash1.ts, 0, 0))
>T : Symbol(T, Decl(inferenceFromGenericClassNoCrash1.ts, 2, 26))
>args : Symbol(args, Decl(inferenceFromGenericClassNoCrash1.ts, 2, 41))
>Base : Symbol(Base, Decl(inferenceFromGenericClassNoCrash1.ts, 2, 68))
>T : Symbol(T, Decl(inferenceFromGenericClassNoCrash1.ts, 2, 26))
class Container<T> {
>Container : Symbol(Container, Decl(inferenceFromGenericClassNoCrash1.ts, 2, 80))
>T : Symbol(T, Decl(inferenceFromGenericClassNoCrash1.ts, 3, 16))
t: T;
>t : Symbol(Container.t, Decl(inferenceFromGenericClassNoCrash1.ts, 3, 20))
>T : Symbol(T, Decl(inferenceFromGenericClassNoCrash1.ts, 3, 16))
}
RenderFlagsMixin(Container);
>RenderFlagsMixin : Symbol(RenderFlagsMixin, Decl(inferenceFromGenericClassNoCrash1.ts, 0, 0))
>Container : Symbol(Container, Decl(inferenceFromGenericClassNoCrash1.ts, 2, 80))

View File

@ -0,0 +1,29 @@
//// [tests/cases/compiler/inferenceFromGenericClassNoCrash1.ts] ////
=== inferenceFromGenericClassNoCrash1.ts ===
// https://github.com/microsoft/TypeScript/issues/61633#issuecomment-2841778576
function RenderFlagsMixin<T extends new (...args: any[]) => object>(Base?: T) {}
>RenderFlagsMixin : <T extends new (...args: any[]) => object>(Base?: T) => void
> : ^ ^^^^^^^^^ ^^ ^^^ ^^^^^^^^^
>args : any[]
> : ^^^^^
>Base : T | undefined
> : ^^^^^^^^^^^^^
class Container<T> {
>Container : Container<T>
> : ^^^^^^^^^^^^
t: T;
>t : T
> : ^
}
RenderFlagsMixin(Container);
>RenderFlagsMixin(Container) : void
> : ^^^^
>RenderFlagsMixin : <T extends new (...args: any[]) => object>(Base?: T) => void
> : ^ ^^^^^^^^^ ^^ ^^^ ^^^^^^^^^
>Container : typeof Container
> : ^^^^^^^^^^^^^^^^

View File

@ -4,11 +4,9 @@
declare function wrap<X>(x: X): { x: X };
declare function call<A extends unknown[], T>(x: { x: (...args: A) => T }, ...args: A): T;
// This should be of type `number` - ideally, it also would not error.
const leak = call(wrap(<T>(x: T) => x), 1);
//// [nestedGenericSpreadInference.js]
"use strict";
// This should be of type `number` - ideally, it also would not error.
var leak = call(wrap(function (x) { return x; }), 1);

View File

@ -22,13 +22,12 @@ declare function call<A extends unknown[], T>(x: { x: (...args: A) => T }, ...ar
>A : Symbol(A, Decl(nestedGenericSpreadInference.ts, 1, 22))
>T : Symbol(T, Decl(nestedGenericSpreadInference.ts, 1, 42))
// This should be of type `number` - ideally, it also would not error.
const leak = call(wrap(<T>(x: T) => x), 1);
>leak : Symbol(leak, Decl(nestedGenericSpreadInference.ts, 4, 5))
>leak : Symbol(leak, Decl(nestedGenericSpreadInference.ts, 3, 5))
>call : Symbol(call, Decl(nestedGenericSpreadInference.ts, 0, 41))
>wrap : Symbol(wrap, Decl(nestedGenericSpreadInference.ts, 0, 0))
>T : Symbol(T, Decl(nestedGenericSpreadInference.ts, 4, 24))
>x : Symbol(x, Decl(nestedGenericSpreadInference.ts, 4, 27))
>T : Symbol(T, Decl(nestedGenericSpreadInference.ts, 4, 24))
>x : Symbol(x, Decl(nestedGenericSpreadInference.ts, 4, 27))
>T : Symbol(T, Decl(nestedGenericSpreadInference.ts, 3, 24))
>x : Symbol(x, Decl(nestedGenericSpreadInference.ts, 3, 27))
>T : Symbol(T, Decl(nestedGenericSpreadInference.ts, 3, 24))
>x : Symbol(x, Decl(nestedGenericSpreadInference.ts, 3, 27))

View File

@ -21,16 +21,15 @@ declare function call<A extends unknown[], T>(x: { x: (...args: A) => T }, ...ar
>args : A
> : ^
// This should be of type `number` - ideally, it also would not error.
const leak = call(wrap(<T>(x: T) => x), 1);
>leak : number
> : ^^^^^^
>call(wrap(<T>(x: T) => x), 1) : number
> : ^^^^^^
>leak : unknown
> : ^^^^^^^
>call(wrap(<T>(x: T) => x), 1) : unknown
> : ^^^^^^^
>call : <A extends unknown[], T>(x: { x: (...args: A) => T; }, ...args: A) => T
> : ^ ^^^^^^^^^ ^^ ^^ ^^ ^^^^^ ^^ ^^^^^
>wrap(<T>(x: T) => x) : { x: (x: A[0]) => A[0]; }
> : ^^^^^^ ^^^^^^^^^^^^^^^^^^
>wrap(<T>(x: T) => x) : { x: (x: unknown) => unknown; }
> : ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^
>wrap : <X>(x: X) => { x: X; }
> : ^ ^^ ^^ ^^^^^
><T>(x: T) => x : <T>(x: T) => T

View File

@ -0,0 +1,59 @@
// @strict: true
// @noEmit: true
// https://github.com/microsoft/TypeScript/issues/59937
type Ref<T> = {
current: T;
};
type FunctionComponent<P> = (props: P) => unknown;
type ComponentProps<T extends FunctionComponent<any>> =
T extends FunctionComponent<infer P> ? P : {};
type PropsWithoutRef<P> = P extends any
? "ref" extends keyof P
? Omit<P, "ref">
: P
: P;
type ComponentPropsWithoutRef<T extends FunctionComponent<any>> =
PropsWithoutRef<ComponentProps<T>>;
declare function forwardRef<T, P>(
component: (props: P, ref: Ref<T>) => unknown,
): (props: P & { ref?: Ref<T> }) => unknown;
const ComponentWithForwardRef = forwardRef(
<T extends FunctionComponent<any>>(
props: ComponentPropsWithoutRef<T>,
ref: Ref<HTMLElement>,
) => {
return null;
},
);
type Test<T> = T extends { component?: infer Component }
? Component extends FunctionComponent<any>
? ComponentProps<Component>
: never
: never;
// the first one here has a chance to pollute the cache
type Result1 = ComponentProps<typeof ComponentWithForwardRef>;
// that could be incorrectly reused by this one
type Result2 = Test<{ component: typeof ComponentWithForwardRef }>; // no `T` leak
// same as ComponentWithForwardRef above but using a resolved signature instead of a direct inferred result of `forwardRef`
declare const ComponentWithForwardRef2: <T extends FunctionComponent<any>>(
props: PropsWithoutRef<ComponentProps<T>> & {
className?: string;
as?: T | undefined;
} & {
ref?: Ref<HTMLElement> | undefined;
},
) => unknown;
type Result3 = ComponentProps<typeof ComponentWithForwardRef2>;
type Result4 = Test<{ component: typeof ComponentWithForwardRef2 }>;

View File

@ -0,0 +1,46 @@
// @strict: true
// @noEmit: true
declare const EffectTypeId: unique symbol;
interface Variance<out A, out E, out R> {
readonly [EffectTypeId]: VarianceStruct<A, E, R>;
}
type Covariant<A> = (_: never) => A;
interface VarianceStruct<out A, out E, out R> {
readonly _V: string;
readonly _A: Covariant<A>;
readonly _E: Covariant<E>;
readonly _R: Covariant<R>;
}
interface Effect<out A, out E = never, out R = never>
extends Variance<A, E, R> {}
declare const succeed: <A>(value: A) => Effect<A>;
type F<X, Y> = Y extends { _type: infer Z }
? X extends Effect<infer A, infer E, infer R>
? Effect<A, E, R | Z>
: X
: X;
type ProxyMap<Service> = {
[K in keyof Service]: (Service & { _type: Service })[K];
};
declare const implement: <T>() => <I extends ReadonlyArray<any>, X>(
x: (...i: I) => X,
) => (...i: I) => F<X, T>;
class XXX {
log = implement<this>()(<N extends number>(n: N) => succeed(n));
}
export declare const inner: XXX;
export declare const outer: ProxyMap<XXX>;
export const a = inner.log(100); // Effect<100, never, never>
export const b = outer.log(100); // Effect<100, never, XXX>

View File

@ -12,3 +12,18 @@ function withP2<P>(p: P) {
const addP2 = withP2({ foo: 1 });
const added2 = addP2({ bar: 2 });
function withP3<P>(p: P) {
const m =
<I,>(from: I) =>
<I2,>(from2: I2) => ({ ...from, ...from2, ...p });
return createTransform(m);
}
const addP3 = withP3({ a: 1 });
const addedSome3 = addP3({ b: '' });
const added3 = addedSome3({ c: true });
const addP3_other = withP3({ foo: 'bar' });
const addedSome3_other = addP3_other({ qwerty: 123 });
const added3_other = addedSome3_other({ bazinga: true });

View File

@ -1,4 +1,5 @@
// @strict: true
interface Thenable<Value> {
then<V>(
onFulfilled: (value: Value) => V | Thenable<V>,

View File

@ -0,0 +1,10 @@
// @strict: true
// @noEmit: true
// https://github.com/microsoft/TypeScript/issues/61633#issuecomment-2841778576
function RenderFlagsMixin<T extends new (...args: any[]) => object>(Base?: T) {}
class Container<T> {
t: T;
}
RenderFlagsMixin(Container);

View File

@ -1,6 +1,6 @@
// @strict: true
declare function wrap<X>(x: X): { x: X };
declare function call<A extends unknown[], T>(x: { x: (...args: A) => T }, ...args: A): T;
// This should be of type `number` - ideally, it also would not error.
const leak = call(wrap(<T>(x: T) => x), 1);