class Parent
extend T::Sig
extend T::Generic
Elem = type_member
sig { returns(Elem) }
def object
# to avoid actually writing the code
T.unsafe(1)
end
end
class Child < Parent[SomeClass]
def print_object
T.reveal_type(object)
end
end
editor.rb:16: Superclasses must only contain constant literals https://srb.help/4002
16 |class Child < Parent[SomeClass]
^^^^^^^^^^^^^^^^^
Errors: 1
There are some other errors, but they're because the inheritance didn't work
Ideally, I'd like to be able to fill in the generic where I'm extending. Maybe there is another way to do this, but if I know what the underlying method is going to return (for example, in graphql-ruby, the object method returns a certain ApplicationRecord class)
I understand why the error exists, _but_ it seems like you can never extend from a class that uses generics, and provide the type for the generic.
In flow (JS) for instance, with React, you extend the Component class and provide the type for Props and State.
type Props = { id: string }
class MyComponent extends React.Component<Props> {
someMethod() {
console.log(this.props.id) // some string
}
}
This already exists, you're just using the wrong syntax:
https://sorbet.run/#%23%20typed%3A%20true%0A%0Aclass%20Parent%0A%20%20extend%20T%3A%3ASig%0A%20%20extend%20T%3A%3AGeneric%0A%0A%20%20Elem%20%3D%20type_member%0A%0A%20%20sig%20%7B%20returns(Elem)%20%7D%0A%20%20def%20object%0A%20%20%20%20%23%20to%20avoid%20actually%20writing%20the%20code%0A%20%20%20%20T.unsafe(1)%0A%20%20end%0Aend%0A%0Aclass%20SomeClass%3B%20end%0Aclass%20Child%20%3C%20Parent%0A%20%20Elem%20%3D%20type_member(fixed%3A%20SomeClass)%0A%20%20%23%20should%20have%20a%20%60something%60%20method%20that%20returns%20an%20integer%0A%20%20def%20print_object%0A%20%20%20%20T.reveal_type(object)%0A%20%20end%0Aend
Note that generics are an intentionally undocumented feature because the experience of using them isn't great yet, so we are unlikely to document this feature in the near future.
Thanks for that!
I understand not wanting to document the generic system, but:
fixed, upper, and lower, and had no idea what they did or meant)I'll use the advice you've given, but it'd be cool to see _some_ docs around it. The metaprogramming has very average DX, but they've got some rudimentary docs. Doesn't have to be complete, just, like, something.
@deecewan I'm not sure if you figured this out but AFAICT:
upper == covariant
lower == contravariant
fixed == invariant
Glad I found this because I was also not sure on the correct way to achieve this. Looking forward to this becoming official and documented 😍