-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Instances of generic interfaces are incompatible because their generic arguments are incompatible; even when two instances in question are structurally identical #61100
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
Comments
I'm not a TS team member Looks like #37052, TS decides that I don't know that I'd call the example "not sensible", but interface ActualWrapper<V> {
value: V;
} And then if you needed a shorthand to say type Wrapper<T extends { value: unknown }> = ActualWrapper<T["value"]>;
declare const thing1: Wrapper<Thing1>;
const thing2: Wrapper<Thing2> = thing1; // okay |
That's because the code was simplified as much as possible, throwing away the parts not relevant to demonstrate the type relationships. The real code is not quite amenable to "your generics should use every piece of information available" rule. |
https://github.com/microsoft/TypeScript/wiki/FAQ?#structural-vs-instantiation-based-inference I can see how you'd get into this state if you were using an object in lieu of many different type parameters? But it's not clear why you would have an extra property in that situation. A better motivating scenario would be helpful. |
Yes exactly I use an object where each property affects a particular aspect of generic type instantiated with that object as a type parameter - which methods are available, whether the arguments of those methods are optional or required and so on, typical type-level programming stuff. If that use case is not important that's fine. Why an object instead of a number of separate type parameters? With object, the parameters are named, not positional; also, all parameters are optional - with separate type parameters, if you need just one, you have to provide all that go before it. Having named generic parameters would help I suppose. |
This issue has been marked as "Not a Defect" and has seen no recent activity. It has been automatically closed for house-keeping purposes. |
🔎 Search Terms
"type relationships" "type compatibility" instances generic interface "type parameter" measuring variance
🕗 Version & Regression Information
⏯ Playground Link
https://www.typescriptlang.org/play/?ts=5.7.3#code/JYOwLgpgTgZghgYwgAgCoAtQHMCMyDeAUMicgG5wA2ArhAFzIDOYU2A3IQL6GGiSyIUGbACYCxUhRr0mLdhJIQAHizgNmrEFg7de4aPCTIA6lDgAHc9AA8wrcmWQQAE0YEptBtRABrEAHsAdxBOAD5xUnIqTzRMLQBtAHIPCESAXR0eZwgESjgoFAR-EGZkMDjcBlMLKyhbCpxQjiKSsDKKkSqzSxs7LBFwgF527BwOHjAATytkAHF-f2dqnrq+hxUIFzd8FK9fAOCw5GH8TmQAMgjJaJk+pJT0nXHs3PzC4tKsBec+nAZ5xbLWr1UZNQgtT7fPqdObfIG9DpDZBfRa-DhAA
💻 Code
🙁 Actual behavior
extra
is not used at all in the definition ofWrapper
, but somehow it affects the compatibility between different instantiations ofWrapper
.🙂 Expected behavior
No error,
Wrapper<Thing1>
andWrapper<Thing2>
are structurally identical and should ideally be the same type internally.Additional information about the issue
The error does not happen if
Wrapper
is defined as an intersection with a dummy{}
type:The only similar issue that I managed to find is Generic interfaces flagged incompatible, as if nominal typing [fixed], which does not produce an unexpected error any more, but also is marked "Working as intended". The explanation is that it's a result of an optimization, and "This optimization depends on types being sensible".
If this is indeed a result of the optimization which is suppressed by using an intersection type, the question is how reliable that suppression is.
Also, I don't see anything not sensible in the example code - in the real code, types
Thing1
andThing2
are defined in the user code, and theWrapper
is defined in the library that only cares about one particular aspect of things.The text was updated successfully, but these errors were encountered: