ОБНОВЛЕННЫЙ ВОПРОС (один основной вопрос)
Учитывая приведенный ниже фрагмент кода, почему тип сужается при объявлении константы как Version
, но не для той, которая объявлена как number
?
type Version = 1 | 2 | 3;
const v: Version = 3;
if (v === 2) console.info('v equals 2'); // Fails compilation with "This comparison appears to be unintentional
// because the types '3' and '2' have no overlap."
const n: number = 3;
if (n === 2) console.info('n equals 2'); // No compile error
ОРИГИНАЛЬНЫЙ ПОСТ
Учитывая фрагмент кода ниже:
...types '3' and '2'...
, а не ...types 'Version' and '2'
?type Version = 1 | 2 | 3;
const v: Version = 3;
if (v > 2) console.info('v is greater than 2');
if (v === 3) console.info('v equals 3');
if (v === 2) console.info('v equals 2'); // Fails compilation with "This comparison appears to be unintentional
// because the types '3' and '2' have no overlap."
Когда TypeScript видит const v: Version = 3;
, он игнорирует Version
и определяет тип как тип числового литерала 3
.
Если v
есть 3
:
(3 > 2)
Никаких ошибок(3 === 3)
Никаких ошибок(3 === 2)
Ошибка «3» и «2» не пересекаются.В следующем примере v
— это параметр функции, который выводится как Version
, а не 3
. Все работает так, как и следовало ожидать, без ошибок.
type Version = 1 | 2 | 3;
function test(v: Version) {
if (v > 2) console.info('v is greater than 2'); // No errors
if (v === 3) console.info('v equals 3'); // No errors
if (v === 2) console.info('v equals 2'); // No errors
}
test(3);
// Logs:
// "v is greater than 2"
// "v equals 3"
При использовании const v: Version = 3
TS сужается от Version
до 3
. Тогда анализ потока управления в каждом операторе if
в некоторых случаях сужается до never
.
const v: Version = 3;
if (v > 2) {
type t = typeof v; // 3
}
if (v === 3) {
type t = typeof v; // 3
}
if (v === 2) {
type t = typeof v; // never
}
if (v !== 3) {
type t = typeof v; // never
}
if (v !== 2) {
type t = typeof v; // 3
}
При использовании const v: number = 3;
TS НЕ сужается от number
до 3
. Тогда анализ потока управления не сможет сузиться number
до более конкретного типа.
const v: number = 3;
if (v > 2) {
type t = typeof v; // number
}
if (v === 3) {
type t = typeof v; // number
}
if (v === 2) {
type t = typeof v; // number
}
if (v !== 3) {
type t = typeof v; // number
}
if (v !== 2) {
type t = typeof v; // number
}