1) useExisting не создаёт новый экземпляр зависимости, а создаёт ссылку на него под другим классом, служащим ему заменой (алиасом).
не ссылку и не под другим классом.
Когда провайдишь сущность, ты сообщаешь di-контейнеру (у нас это инжектор) di-токен, по которому инжектор выдает тебе сущности.
Класс для него это частный случай di-токена.
Можно ведь и так сделать
providers: [{
provide: 'doc',
useExisting: DOCUMENT
}]
Подробнее тут
https://angular.io/guide/dependency-injection-prov...
2) useExisting следует использовать вместе с useClass
Опять же, не обязательно класс, главное чтобы сущность связанная с токеном в useExisting была уже известна инжектору.
3) класс-алиас, который внедряем должен полностью соответствовать интерфейсу оригинального класса на который мы собираемся заменить.
Не обязательно, инжектор твои типы не проверяет, просто выдает то что он запомнил.
А по главному вопросу
Когда следует использовать UseExistingProvider?
Когда тебе нужно существующую сущность предоставить под другим токеном. Допустим какие-то другие классы инжектят себе зависимости по им известному токену, вот, чтобы они по нему нашли наш инстанс.
В ангуляре полно такого, HttpClient инжектит
HTTP_INTERCEPTORS
, директивы форм инжектят
NG_VALIDATORS
, бутстрап инжектит
APP_INITIALIZER
и т.д.
Вместе с именно классами useExisting практически не используется, не вижу смысла.