if (typeof key !== 'string') {
      throw err(
        'A key option with a unique string value must be provided when creating a selector.',
      );
    }
ExecutionInfo is useful for managing async work and resolving race
conditions. It keeps track of the following:

1. The dep values found so far for the latest running execution. This is
   useful for answering the question "given a new state, have any of the
   async execution's discovered dep values changed?"
2. The latest loadable, which holds the loadable of the latest execution.
   This is important because we need to return this loadable when the
   selector's result is requested and there is a pending async execution. We
   are essentially caching the latest loading loadable without using the
   actual selector cache so that we can avoid creating cache keys that use
   partial dependencies (we never want to cache based on partial
   dependencies).
3. The latest execution ID, which is needed to know whether or not an async
   execution is stale. At any point in time there may be any number of stale
   executions running, but there is only one 'latest' execution, which
   represents the execution that will make its way to the UI and make updates
   to global state when it finishes.
4. The set of stateVersions which have already been tested as valid for this
   evalution.  This is an optimization to avoid having to transitively
   check if any deps have changed for a state we have aleady checked.
   If additional async dependencies are discovered later, they may have
   different values in different stores/states, so this will have to be
   cleared.