-
Notifications
You must be signed in to change notification settings - Fork 12.8k
inconsistent behavior of interface vs type alias as a generic parameter with constraint #28174
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 aware that interfaces are not quite exactly the same as a type alias. I also assume that the anonymous(?) generic parameter (see There's nothing in the documentation that indicates why this might occur, though: https://www.typescriptlang.org/docs/handbook/advanced-types.html#interfaces-vs-type-aliases |
The constraint It's somewhat unfortunate to have this subtle difference between interface and object literal types, but it is the best rule we've been able to devise to allow us to leverage knowledge that object literals have only the properties they themselves declare, thus making it safe to implicitly add an index signature. Meanwhile, you can fix the issue using a self-referential constraint: type Container<X extends Record<keyof X, () => any>> = {}; |
Thank you so much for clearifying. I was going crazy over this for quite a while now, because I couldn't figure out what was going on. Unfortunately this a huge drawback for interfaces in my opinion. The self-referential constraint seems like a hack at best in my opinion, because its only works on generics. It makes it basically impossible, to write a reusable (e.g. a type/interface) constrains for an interface. You would have to repeat that constrain in every place where you want to use it, which could lead to massive code duplication. The problem is you can do this with a generic, which would allow interfaces without index signatures to be passed in: function F<T extends { values: Record<keyof T['values'], string> }>(t: T) {}; But you can't do this (neither as a type nor as an interface): interface I { values: Record<keyof I['values'], string> }
// ERROR: 'values' is referenced directly or indirectly in its own type annotation. Therefor I can't use it like that (which would be great, especially in cases where I use function F<T extends I>(t: T) {}; |
TypeScript Version: 3.1.3
Search Terms:
generic parameter extends record named anonymous interface type alias constraint inconsistent different
Code
Expected behavior:
Consistent behavior as a generic parameter regardless of whether a type is expressed as an interface, a type alias, and an anonymous (?) type. I'm not actually sure whether these are supposed to be valid or not, but I would expect them to be consistent.
Actual behavior:
The compiler only generates an error for the interface representations of the type.
Playground Link:
playground with above code
Related Issues:
none?
The text was updated successfully, but these errors were encountered: