There are four forms: useClass (provide a class), useValue (provide a static value or mock), useFactory (provide the return value of a factory function — supports async and DI via the inject array), and useExisting (alias one token to another already-registered provider).
useClass — swap implementations (e.g., mock vs real service).
useValue — inject constants, config objects, or mock instances.
useFactory — when provider creation requires async work or other dependencies.
useExisting — create an alias so two tokens point to the same instance.