-
Notifications
You must be signed in to change notification settings - Fork 12.9k
Defer inference for homomorphic mapped types #20711
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
1. Actually return the cached result! 2. Unnest worker function. 3. Improve all the names. 4. Pre-set the cache to undefined to avoid loops. (Not sure this is needed, though.) 5. Make the new type internal to avoid baseline changes. 6. Cut off recursion in the printing of recursive deferred mapped types. Note that (6) required introducing a new stack that is exactly like mappedTypeStack. I think the cache may actually be needed here, not in the creation of the deferred type.
Compilation didn't finish before! Now it does.
Just print {} for the type of deferred symbols. This is simple although it loses fidelity pretty badly. It will not be sufficient for projects that want to export the result of an inference. I don't think any such projects exist right now, though.
Do you have any tests for quickinfo for one of these deferred types? If it's the same as the type baselines, I'm not sure it'd be a great experience - minimally it'd be a degradation over our current experience, which is never good. |
This allows index signature inference to be inferred as well.
A deferred mapped type with a source that has an index signature now prints {} as the type of the index signature. This avoids an infinite recursion.
@ahejlsberg I think this is ready for you to look at. |
@weswigham I added quickinfo and completion tests. I didn't add signature info tests since deferred inferred types do not have signatures, at least until we decide to try to infer those too. Given that limitation, the editing experience is .. OK. Completions are fine but quick info just displays I'm going to try putting in a depth cutoff to the printing, which will cover the common, non-recursive case of depth=1 better. |
This makes them compatible in d.ts and slightly less misleading in services.
@weswigham After playing with a cutoff, and then discussion with @mhegazy, I decided to keep the current solution, but emit |
src/compiler/checker.ts
Outdated
function inferTypeForHomomorphicMappedType(source: Type, target: MappedType, mappedTypeStack: string[]): Type { | ||
function inferTypeForHomomorphicMappedType(source: Type, target: MappedType): Type { | ||
const key = source.id + "," + target.id; | ||
if (deferredInferenceCache.has(key)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we actually need this cache?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, turns out some of the tests run out of memory without it.
src/compiler/types.ts
Outdated
@@ -3601,6 +3609,12 @@ namespace ts { | |||
finalArrayType?: Type; // Final array type of evolving array type | |||
} | |||
|
|||
/* @internal */ | |||
export interface DeferredMappedType extends ObjectType { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would call this ReverseMappedType
.
src/compiler/types.ts
Outdated
@@ -3494,6 +3501,7 @@ namespace ts { | |||
EvolvingArray = 1 << 8, // Evolving array type | |||
ObjectLiteralPatternWithComputedProperties = 1 << 9, // Object literal pattern with computed properties | |||
ContainsSpread = 1 << 10, // Object literal contains spread operation | |||
Deferred = 1 << 11, // Object contains a deferred inferred property |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ReverseMapped
?
src/compiler/types.ts
Outdated
@@ -3260,6 +3261,12 @@ namespace ts { | |||
isRestParameter?: boolean; | |||
} | |||
|
|||
/* @internal */ | |||
export interface DeferredTransientSymbol extends TransientSymbol { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ReverseMappedSymbol
?
src/compiler/checker.ts
Outdated
inferTypes(inferences, sourceType, templateType, 0, mappedTypeStack); | ||
return inference.candidates ? getUnionType(inference.candidates, UnionReduction.Subtype) : emptyObjectType; | ||
} | ||
function inferDeferredMappedType(sourceType: Type, target: MappedType): Type { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getTypeOfReverseMappedSymbol
and pass in the symbol.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is called separately when getting the type of the index signature, which doesn't have a symbol. However, I think uniformity is valuable enough here to create a simple getTypeOfReverseMappedSymbol
that delegates to the original.
Fixes #19951 in a more scalable way by deferring inference on property that result from inference of homomorphic mapped types. It makes lodash's uses of PartialDeep have very little overhead, since those inferences are lower priority and will never be fully instantiated.
The principle drawback to this is that printing an inferred mapped type is non-trivial. I poked at the problem for a while and didn't arrive at a satisfactory solution. In this PR I just use
{}
for printing the type of all deferred symbols. This is fine for interactive use, OK for our baselines, and not sufficient for packages that want to generate a .d.ts from a file that exports an inferred mapped type. However, I don't think this happens often.This PR obsoletes #20622.