Problem/Motivation
Currently, when we call `$node = $entity_type_manager->getStorage('node')->load(123);`, static analysis has no straightforward way to know the type of `$node`. It only knows that it is an entity.
There are tools like https://mglaman.dev/blog/better-static-analysis-entity-type-storages-php..., but this is very specific to phpstan, not clear that it will be understood by IDEs etc.
Steps to reproduce
Proposed resolution
Put a `@template TEntity of EntityInterface` on `EntityStorageInterface`.
Document the return type of e.g. EntityStorageInterface::load() as `(TEntity&EntityInterface)|null`.
TBD:
Provide a method `EntityTypeManager->getStorageByClass(string $class)`, which is documented to return an instance of `EntityStorageInterface<$class>`.
The mapping logic here would be similar to EntityTypeRepository::getEntityTypeFromClass(), but it would also have to support interfaces. The mapping can be cached somewhere.
If an interface is used by more than one type, throw an exception.
Open questions
We could decide if this belongs into EntityTypeManager or some other place.
Difficulties
I can already see one flaw of this proposed system.
We can have code that calls $entity_type_manager->getStorageByClass(NodeInterface::class)` which works.
Then somebody introduces a new entity type with `MyEntityInterface extends NodeInterface` or just `MyEntity implements NodeInterface`, and all of that existing code will break, because now the interface is ambiguous.
We could use the actual entity class, but I don't like it.
Or we could a have a method that takes the entity type id _and_ the interface.
Or we could simply use `->getStorage($entity_type_id)`, but then calling code can put `@var EntityStorageInterface $storage` on the variable.
Optional changes
Optionally, also add `@template TEntityId of int|string` on EntityStorageInterface.
To properly support this we would need `getConfigStorageByClass($class)` and `getContentStorageByClass($class)` which would provide different key types. But I think it provides little benefit for the cost.
Remaining tasks
User interface changes
Introduced terminology
API changes
Data model changes
Release notes snippet