In Rails event store, AggregateRoot has DSL methods that result in blocks with this shape:
class X
extend AggregateRoot::OnDSL
class MyEvent < RailsEventStore::Event; end
on MyEvent do |event|
# Code
end
end
Inside that block, there's access to the class instance data. But sorbet don't know about it.
Is there a way to tell Sorbet that that block will be injected as an instance method?
I can mark every use of fields or methods as T.unsafe(), but that would remove the typing from it, and adding a cast makes the code harder to read
You can use
T.bindto communicate to Sorbet thatselfhas a particular type in a particular block:More generally, you can add a shim which specifies the type of a DSL API like this, and specify the type the proc will be bound to, like:
T.proc.bind(TheTypeOfSelfInTheBlock).params(...).returns(...).In this case, it's a bit tricky for
AggregateRoot::OnDSL.on, if not impossible, for two reasons:ontakes a*event_klasses. You can't be sure which event class triggered your block, so you don't statically know which of theevent_klassesthe event passed to your block will be.event_klassesshould beevent_klasses: T.class_of(RailsEventStore::Event). Even if it were one singular value, you would need the generics system to let you express that the block's argument is specifically the type ofevent_klasses(and not just anyRailsEventStore::Event). I don't think that's currently possible.