#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
сужается. Что определенно странно.