В настоящее время мы применяем строгие проверки null в старой кодовой базе и сами создали помощника.
type Maybe<T> = T | null | undefined
Мы реализовали пару вспомогательных функций, они могут выглядеть так:
function isSafe<T>(val: Maybe<T>): val is T {
// ...
}
Работает как шарм, улучшение, которое я хотел бы, состоит в том, чтобы предотвратить передачу значений, не являющихся возможными, в качестве параметра, потому что с этим типом можно было бы вызвать isSafe('hi')
, что не может быть null
, что является случай для каждой переменной, которая не заключена в Maybe
.
Предотвращение подобных вызовов устранило бы недоразумения, поскольку я ожидаю, что переменные, которые передаются в isSafe
, будут Maybe
.
К сожалению, я не нашел способа добиться этого, поскольку T | null | undefined
допускает любой из этих типов, а не только комбинацию этих трех.
Есть ли способ добиться ошибки типа при передаче значения, отличного от Maybe
, в функцию?
Бонусные баллы были бы, если бы это также позволяло T | null
и T | undefined
, поскольку мы решили, что будем обрабатывать оба значения одинаково.
Вот решение, которое немного уродливо, но соответствует вашим критериям:
type DefinitelyMaybe<T> = null extends T ? T : undefined extends T ? T : never
function isSafe<T>(val: DefinitelyMaybe<T>): val is NonNullable<typeof val> {
return val !== null && val !== undefined;
}
// Argument of type 'string' is not assignable to parameter of type 'never'.
isSafe('test');
// OK
isSafe('test' as string | undefined);
По сути, DefinitelyMaybe<T>
— это то же самое, что и T
, если null
, undefined
или оба могут быть назначены T
. В противном случае это never
, что приводит к ошибке типа на сайте вызова, потому что аргумент не может быть назначен ему.
Хорошо, если в одном месте некрасиво, а в других красивее :) Но действительно умное решение, спасибо