Почему нельзя использовать typeof B как тип напрямую в TypeScript?
Что проверяют
Различаете ли вы два разных typeof: оператор времени выполнения и запрос типа в позиции типа. И понимаете ли, что у класса две стороны, статическая и экземплярная.
Как отвечать
В позиции типа typeof работать умеет, это штатный запрос типа: из const cfg = { port: 8080 } тип получают как type Cfg = typeof cfg. Проблемы начинаются в двух местах.
Первое: typeof B, где B это класс, даёт тип конструктора, то есть статическую сторону со статическими полями и сигнатурой new. Тип экземпляра называется просто B, потому что объявление класса создаёт одновременно и значение, и тип.
class B { x = 1; static make() { return new B(); } }
let a: B; // экземпляр, есть поле x
let b: typeof B; // сам класс, b = B, дальше new b()
type Inst = InstanceType<typeof B>; // снова экземплярВторое: typeof принимает только идентификатор или цепочку свойств, но не произвольное выражение. Запись вида typeof getUser() невалидна. Для результата функции берут ReturnType<typeof getUser>, для элемента массива (typeof arr)[number], для значений объекта индексный доступ по ключам.
Третий случай: typeof нельзя применить к интерфейсу или псевдониму типа. Значения в рантайме у них нет, применять запрос типа не к чему.
Где спотыкаются
Говорят, что typeof в типах использовать нельзя. Это прямая ошибка, и звучит она как незнакомство с языком: на запросе типа держатся вывод типа конфигурации, типизация фабрик и работа с константными объектами.
Второе: пишут let b: typeof B и ждут экземпляр. Компилятор молчит, ошибка вылезает позже: поля x у такой переменной нет, зато есть статический метод, и человек ищет причину в логике, а не в типе.
Третье: берут typeof от изменяемого значения и ждут литеральных типов. Поля обычного объекта выводятся расширенно, вместо конкретного числа получается number, вместо набора строк string. Нужен as const, иначе объединение по значениям не собрать.