В вашем первом примере B расширяет логическое значение. Это позволяет Typescript более строго определять тип и позволяет уменьшить B до true
или false
по мере необходимости. Рассмотрим:
const test: X<boolean> = {b1: true, a2: 2}; // Compiles. Likely not what you want
const test2: X<true> = {b1: true, a2: 2}; // Does not compile, as expected
Это означает, что когда вы вызываете f2, тип { b1: true, a1: 1 }
на самом деле X<true>
, а { b1: false, a2: 2}
- X<false>
.
В этом примере если вы назначите результат переменной, он не будет компилироваться, так как вы не сможете строго определить тип.
function f2(b: boolean) {
const argument = b ? { b1: true, a1: 1 } : { b1: false, a2: 2 };
// type is { b1: boolean; a1: number; a2?: undefined } | { b1: boolean; a2: number; a1?: undefined; }
f(argument); // compile error
}
Во втором примере в Typescript просто недостаточно информации для оценить тип при типе компиляции.
Эта модификация вашей второй функции позволяет ей компилировать
function f2(b: { b1: boolean }) {
if (b.b1) {
f({ b1: true, a1: 1 })
} else {
f({ b1: false, a2: 2 })
}
}
Для получения дополнительной информации об условных типах отметьте https://www.typescriptlang.org/docs/handbook/advanced-types.html#conditional -типы