Which type would you define here?

I have a module, say Event to keep it simple, whose purpose is to serve as a basis for a bunch of specialized structs FooEvent, BarEvent, etc.

defmodule FooEvent do
  use Event
  ...
end

defmodule BarEvent do
  use Event
  ...
end

OK, in general, the code base works with events, of any type, protocols and friends take care of the details:

defmodule KafkaClient do
  def broadcast(event) do
    ...
  end
end

Given this design, I believe it would be natural to have a type Event.t() for the specs of functions like the one above and my current choice is

defmodule Event do
  @type t() :: struct()
  ...
end

However, Event itself is not a struct. Is that type definition idiomatic, or would you choose a different type equivalence?

In case it matters, I want this for documentation purposes only, won’t run Dialyzer.

t doesn’t need to be a struct, it can be a ripple a nested lost or even any.

I know, I know. I chose struct because the concrete events that get passed in practice are structs.

My question is about the choice. Would you pick a different type equivalence? What would be idiomatic?

Then perhaps list the individual structs you expect:

@type t :: Foo1 | Foo2 | ...

As you say it’s for documentation, so make it as explicit as necessary for making the reader able to actually use that type.