Не понимаю, почему тип не сужается внутри проверки if

#typescript

Вопрос:

Пытаюсь понять, почему я получаю рассматриваемую ошибку.

 type Result = {
  loading: true,
} | {
  loading: false,
  data: string | Error,
};

function getResult(): Result {
  return { loading: false, data: new Error("Hello!") }
}

interface ILoadingOrError {
  result: {
    loading: true,
  } | {
    loading: false,
    data: Error,
  }
}

function y(param: ILoadingOrError): void {
  if(param.result.loading) {
    console.log("loading");
  } else {
    console.log(param.result.data.message);
  }
}

function x() {
  const r = getResult();
  if (r.loading === true || r.data instanceof Error) {
    // Type 'Result' is not assignable to type '{ loading: true; } | { loading: false; data: Error; }'.
    // Type '{ loading: false; data: string | Error; }' is not assignable to type '{ loading: true; } | { loading: false; data: Error; }'.
    //   Type '{ loading: false; data: string | Error; }' is not assignable to type '{ loading: false; data: Error; }'.
    //     Types of property 'data' are incompatible.
    //       Type 'string | Error' is not assignable to type 'Error'.
    //         Type 'string' is not assignable to type 'Error'.(2322)
    y({result: r});
  }
}

x();
 

Внутри условия if гарантируется, что r это либо {loading: true} или {loading: false, data: Error} .

Это ошибка сужения, или я что-то неправильно понимаю в том, как должно работать сужение типов?

ИЗМЕНИТЬ: Я подал это как проблему в машинописном тексте. Похоже, что, хотя это должно сработать, это слишком сильно замедлит компиляцию.

Защита типов не распространяет сужения типов на родительские объекты. Сужение применяется только при доступе к суженному свойству, поэтому функция разрушения работает, а функция ссылки-нет. Сужение родительского элемента потребует синтеза новых типов, что будет дорогостоящим. Более подробно в этом комментарии.

Комментарии:

1. y({result: { loading: r.loading, data: r.data }}); работает tsplay.dev/WPjJJN, но в этом действительно не должно быть необходимости. Похоже, что тип r не сужается, хотя тип r.data сужается. Что определенно странно.