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
This changed between versions 4.05 and 4.1.5 in terms of the error chain and availability of case manipulation types used as a stand-in for more complicated derived types, and between 3.3.3333 and 3.5.1 for the main error, though the latter change appears to be a difference in handling propagation of the case-manipulation-type-unavailability error
This is the behavior in every version I tried, and I reviewed the FAQ for entries about generics
Nightly version at time of test: v5.0.0-dev.20221212
typeSize='Small'|'Medium'|'Large';//Case manipulation is a simplified stand-in for more complex derived typestypeCaseMap={[SinSize]: {lowerCase: Lowercase<S>,upperCase: Uppercase<S>}};typeCaseMapHoverDemo=CaseMap['Medium'];//{lowerCase: "medium"; upperCase: "MEDIUM";}typeValueOf<T>=T[keyofT];//https://stackoverflow.com/a/49286056typeValueOfHoverDemo=ValueOf<CaseMap['Medium']>;//'medium' | 'MEDIUM'typeMyGeneric<SextendsSize>={normalCase: S;caseObj: ValueOf<CaseMap[S]>};typeMyGenericWET<SextendsSize>={normalCase: S;caseObj: ValueOf<{lowerCase: Lowercase<S>,upperCase: Uppercase<S>}>};typeMyGenericHoverDemo=MyGeneric<'Medium'>;declarefunctiontakesAnySizeDirectly(mainParam: Size): any;declarefunctiontakesAnySizeObject(mainParam: MyGeneric<Size>): any;declarefunctiontakesAnySizeObjectWET(mainParam: MyGenericWET<Size>): any;exportconsttakesOneSize=function<SextendsSize>(size: S,mainParam: MyGeneric<S>){takesAnySizeDirectly(size);//S, which extends Size, is assignable to Size: that makes sensetakesAnySizeObject(mainParam);//but MyGeneric<S> is not assignable to MyGeneric<Size>: that does not/* Error ts(2345): Argument of type 'MyGeneric<S>' is not assignable to parameter of type 'MyGeneric<Size>'. (It seems like it should be though.) Types of property 'caseObj' are incompatible. Type 'ValueOf<CaseMap[S]>' is not assignable to type 'ValueOf< { lowerCase: "medium"; upperCase: "MEDIUM"; } | { lowerCase: "small"; upperCase: "SMALL"; } | { lowerCase: "large"; upperCase: "LARGE"; } >'. (It seems like it should be though.) */}exportconsttakesOneSizeWorks=function<SextendsSize>(size: S,mainParam: MyGenericWET<S>){takesAnySizeDirectly(size);//S, which extends Size, is assignable to SizetakesAnySizeObjectWET(mainParam);//and MyGenericWET<S> is assignable to MyGenericWET<Size>}
🙁 Actual behavior
Error as shown when reusing the type CaseMap[S] instead of repeating the type it represents in the definition of MyGeneric.
TS doesn't even allow a direct cast, claiming Conversion of type 'MyGeneric<S>' to type 'MyGeneric<Size>' may be a mistake because neither type sufficiently overlaps with the other.
Note that naming the repeated type doesn't help with the error, but the motivating example doesn't provide a clear way to avoid using the map structure.
🙂 Expected behavior
No errors in the above. MyGeneric is actually equivalent to MyGenericWET, takesAnySizeObject is actually equivalent to takesAnySizeObjectWET, and takesOneSize is equivalent to takesOneSizeWorks.
Possible cross-links
This might be related to #49505 which seems to focus more on type inference and chained generic functions. That refers to #30215 (a 2019 PR released in v3.4 which enabled “inference of generic function type results for generic functions that operate on other generic functions.”) Here, we don’t have generic functions operating on other generic functions, at least where “functions” is used in the JavaScript sense.
The text was updated successfully, but these errors were encountered:
The problem here is variance measurement -- ValueOf<T> appears to be invariant due to its simultaneous co and contravariant observation on T, but in reality it's just covariant. When instantiated with a concrete object type like in the WET variant, this isn't an issue, because the type is simply instantiated and compared that way. But given an arbitrary deferred type like CaseMap[S], there isn't a procedure we can do (apart from just hardcoding inconsistent behavior that T[keyof T] means something special/magic) which would determine that there isn't a manifestable soundness violation here.
Bug Report
🔎 Search Terms
generic extends assignable
🕗 Version & Regression Information
⏯ Playground Link
Playground link with relevant code
💻 Code
🙁 Actual behavior
Error as shown when reusing the type
CaseMap[S]
instead of repeating the type it represents in the definition of MyGeneric.TS doesn't even allow a direct cast, claiming
Conversion of type 'MyGeneric<S>' to type 'MyGeneric<Size>' may be a mistake because neither type sufficiently overlaps with the other.
Note that naming the repeated type doesn't help with the error, but the motivating example doesn't provide a clear way to avoid using the map structure.
🙂 Expected behavior
No errors in the above.
MyGeneric
is actually equivalent toMyGenericWET
,takesAnySizeObject
is actually equivalent totakesAnySizeObjectWET
, andtakesOneSize
is equivalent totakesOneSizeWorks
.Possible cross-links
This might be related to #49505 which seems to focus more on type inference and chained generic functions. That refers to #30215 (a 2019 PR released in v3.4 which enabled “inference of generic function type results for generic functions that operate on other generic functions.”) Here, we don’t have generic functions operating on other generic functions, at least where “functions” is used in the JavaScript sense.
The text was updated successfully, but these errors were encountered: