#typescript
Вопрос:
Как я могу проверить, если значение, инициализированное как null или число, больше 4 в машинописном тексте? см.Пример.
years: number | null;
это приведет к ошибке машинописного текста «Объект, возможно, «нулевой»».
(years > 4)
Комментарии:
1. Что ж, в этом нет ничего плохого… Если вы проверяли раньше и уверены, что это не null, вы можете сделать (лет! > 4), чтобы сообщить ide, что это точно не null, в противном случае проверьте на null, в общем, я бы не стал комбинировать опцию с null и числом
2. Задумывались ли вы над выражением:
(years amp;amp; years > 4)
? Или даже(typeof years === "number" amp;amp; years > 4)
?3. @CRice Да, но необходимость повторять это выражение каждый раз вызывает боль — я думаю, что OP спрашивает о том, как кодировать ограничение диапазона в качестве типа предиката- к сожалению, TS не поддерживает «реальные» типы предикатов, но вы можете использовать typedef и функцию защиты в качестве типа предиката.
4. Если мы просто пытаемся избежать повторения, то, возможно, предложение Шай будет лучшим. JS преобразуется
null
0
в это сравнение, так что оно будет работать нормально, даже еслиyears
естьnull
. И добавление!
этого не позволит машинописному тексту жаловаться на это.5. @Dai да, это именно то, о чем я спрашивал
Ответ №1:
Я предполагаю, что вы спрашиваете, как вы можете выразить статическое требование, которому всегда удовлетворяет параметр функции (или возвращаемое значение, или значение свойства класса) с именем x
( x is number amp;amp; x > 4 ) | null
.
…который также известен как Тип предиката, Тип уточнения или Зависимый тип.
К сожалению, TypeScript (насколько мне известно) еще не поддерживает истинные типы уточнений или типы предикатов (хотя его возможности анализа потоков почти доступны), но вы почти можете достичь этого с помощью определения типа и защиты типа:
type NumberGT4OrNull = null | ( number amp; { _isGT4: never } );
function isNumberGT4OrNull( x: unknown ): x is NumberGT4OrNull {
if( typeof x === 'number' ) {
return x > 4;
}
return false;
}
- Объявление типа
type NumberGT4OrNull = null | number;
слишком допустимо, так как1
, например, оно соответствует значению. - Что делает его сумма типа с членом набирается как
never
означает, что нет буквальное значение (или любое другое значение), возможной в рамках на TypeScript или JavaScript не может сравнитьсяNumberGT4OrNull
— по крайней мере, не без использования пользовательского типа-охранникisNumberGT4OrNull
, который предотвращает случайное, используя любое значение не проверяетсяisNumberGT4OrNull
в параметр, возвращаемое значение или свойство с типомNumberGT4OrNull
.- …за исключением
null
, потому что в этом случаеnull
ключевое слово находится вне типа суммы сnever
.- Но если вы хотите, чтобы для проверки требовались четные
null
значения, используйтеtype NumberGT4OrNull = ( null | number ) amp; { _isGT4: never };
.
- Но если вы хотите, чтобы для проверки требовались четные
- Недостатком является то , что вы не можете не использовать
isNumberGT4OrNull
, но это не такая уж большая проблема в общей схеме вещей.
- …за исключением
Используется так:
function acceptsValue( value: NumberGT4OrNull ): void {
}
//
const userInput = prompt("Enter number");
acceptsValue( userInput ); // Error: userInput is a string
const userInputNumber = parseInt( userInput, 10 );
acceptsValue( userInputNumber ); // Error: userInputNumber is not NumberGT4OrNull
if( isNumberGT4OrNull( userInputNumber ) ) {
acceptsValue( userInputNumber ); // OK! TSC knows `userInputNumber` is `NumberGT4OrNull`.
}
Как было сказано выше, использование never
означает, что буквальное значение не будет совпадать, поэтому следующее не будет работать и приведет к ошибкам:
acceptsValue( 3 ); // Error
acceptsValue( 4 ); // Error
acceptsValue( 5 ); // Error
acceptsValue( null ); // But this is OK
Но вы можете добавить (неисчерпывающий) набор постоянных значений для удобства, если хотите:
type NumberGT4OrNull = null | ( number amp; { _isGT4: never } ) | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16;
// So now, this does work:
acceptsValue( 3 ); // Error
acceptsValue( 4 ); // Error
acceptsValue( 5 ); // OK!
acceptsValue( null ); // Also OK
const n = 17;
acceptsValue( n ); // Error
if( isNumberGT4OrNull( n ) ) {
acceptsValue( n ); // OK!
}
Комментарии:
1. @CRice Я нашел ошибку в своем ответе —
acceptsValue( userInputNumber );
утверждение на самом деле отлично компилируется — я вижу, как я могу заставить его работать правильно, хм.2. Используйте виртуальное свойство в качестве дискриминатора, таким образом, значение должно пройти через защиту типа, прежде чем его можно будет присвоить
acceptsValue
. НАПРИМЕР:type isNumberGT4OrNull = (number | null) amp; {_isGT4: never}
.
Ответ №2:
years
может быть, это число, или или может быть null
. И null > 4
в этом нет никакого смысла.
Поэтому, прежде чем вы это сделаете, вы должны убедиться, что на самом деле это не null
первое.
if (years !== null) {
const isMoreThanFour = years > 4
}
Комментарии:
1. Можно также объединить его в один оператор if:
if (years amp;amp; years > 4)
. Для ссылки:if (years)
возвращаетtrue
, если years не является:null
,undefined
,NaN
, пустой строкой''
,0
, илиfalse
.