     :start_phases
   ]
 
+  application_key_specs = Enum.reduce(@application_keys, &{:|, [], [&1, &2]})
+
+  @type app :: atom
+  @type key :: atom
+  @type application_key :: unquote(application_key_specs)
+  @type value :: term
+  @type state :: term
+  @type start_type :: :normal | {:takeover, node} | {:failover, node}
+  @type restart_type :: :permanent | :transient | :temporary
+
   @doc """
   Returns the spec for `app`.
 

      defoverridable Application
    end
  end

  @type app :: atom
  @type key :: atom
  @type value :: term
  @type state :: term
  @type start_type :: :normal | {:takeover, node} | {:failover, node}
  @type restart_type :: :permanent | :transient | :temporary

  @application_keys [
    :description,

  specification parameter does not exist, this function
  will raise. Returns `nil` if the application is not loaded.
  """
  @spec spec(app, application_key) :: value | nil
  def spec(app, key) when is_atom(app) and key in @application_keys do
    case :application.get_key(app, key) do
      {:ok, value} -> value
