Это предполагаемое поведение, поскольку пути к свойствам в TypeScript могут быть сколь угодно глубокими при изменении типов по пути. Например, совершенно законно написать что-то вроде этого:
declare class Boxed<T> {
contents: T;
doubleBoxed: Boxed<this>
};
declare const b: Boxed<string>
// m: Boxed<Boxed<Boxed<Boxed<Boxed<string>>>>>
const m = b.doubleBoxed.doubleBoxed.doubleBoxed.doubleBoxed;
Таким образом, уже для произвольного типа существует практически бесконечное количество свойств, которые «могут» существовать, и любое из них может иметь какой-то новый тип, никогда ранее не встречавшийся в вашей программе.
Это важно для never
, потому что вы можете написать что-то вроде этого:
// I am here to cause trouble.
type M<T, S> = T extends { nested: { nested: { nested: any } } } ?
S :
{ el: T, nested: M<{ nested: T }, S> };
type F1 = {
prop: M<F1, "foo">
};
type F2 = {
prop: M<F2, "bar">
};
declare const f1: F1;
// f1.prop.nested.nested.nested: "foo"
f1.prop.nested.nested.nested;
declare const f12: F1 & F2;
// OK, infinitely
f12.prop.el.prop.el.prop.el.prop.el.prop;
// 'never' at depth 4...
f12.prop.nested.nested.nested;
На самом деле нет никакого способа предсказать, где вам нужно искать выражения, которые могут привести к never
— определение M
не дало нам никаких подсказок; вы должны действительно понимать этот код как человек, чтобы знать, где исследовать, чтобы найти вложенный never
.
На самом деле, если бы вы могли решить это «правильно» для любой произвольной глубины доступа к свойствам, вы могли бы делать такие вещи, как доказать/опровергнуть гипотезу Коллатца путем структурирования типов, выполняющих арифметические действия (что уже возможно). Очевидно, что это невозможно, поэтому TypeScript не пытается выйти за пределы легко разрешаемого случая свойств верхнего уровня созданного типа.
person
Ryan Cavanaugh
schedule
19.05.2020