You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
5.0: const-like inference is not preserved unless a mapped type is usedΒ #53307
typeNotEmpty<TextendsRecord<string,any>>=keyofTextendsnever ? never : T;constthing=<constOextendsRecord<string,any>>(o: NotEmpty<O>)=>{returno;};constt=thing({foo: ''});// is inferred as { foo: string } β// BUT, when adding a mapped type to NotEmpty it workstypeNotEmptyMapped<TextendsRecord<string,any>>=keyofTextendsnever ? never : {[KinkeyofT]: T[K]// β¬ οΈ};constthingMapped=<constOextendsRecord<string,any>>(o: NotEmptyMapped<O>)=>{returno;};consttMapped=thingMapped({foo: ''});// is inferred as { foo: "" } β
π Actual behavior
When using a non-mapped validator type, the "valid" branch does not preserve the const-like inference unless the type is mapped over.
π Expected behavior
A mapped type is not needed to preserve const-like inference.
I did find it a bit curious that NotEmptyMapped unfortunately doesn't seem to actually error for an empty object, and instead returns Record<string, any>. Is that possibly related?
Both correctly error if the check is instead changed to {} extends T, but have the same const-like inference mismatch.
Finally if the check is T extends Record<string, never>, both don't use const-like inference and NotEmptyMapped doesn't error on an empty object, but NotEmpty does.
I think that's all the ways I can think of to check for an empty object...
Activity
Andarist commentedon Mar 17, 2023
Working case:
{ [K in keyof O]: O[K]; }O["foo"]isConstTypeParameterContextis able to returntruebased on this informationNot working case:
Record<string, any>anyisConstTypeParameterContextreturnfalsebased on thatconorbrandon commentedon Mar 17, 2023
Interesting! Thanks for taking a look.
I did find it a bit curious that
NotEmptyMappedunfortunately doesn't seem to actually error for an empty object, and instead returnsRecord<string, any>. Is that possibly related?Both correctly error if the check is instead changed to
{} extends T, but have the same const-like inference mismatch.Finally if the check is
T extends Record<string, never>, both don't use const-like inference andNotEmptyMappeddoesn't error on an empty object, butNotEmptydoes.I think that's all the ways I can think of to check for an empty object...
ahejlsberg commentedon Mar 17, 2023
It looks like we need to probe types a little deeper in
isConstTypeVariable.