Присвойте параметру универсальной функции значение T | null, чтобы можно было передавать только значения типов, включающих T | null:
function foo<T>(val: T) { ... }
let fooNonNull: string = "foo"
foo(fooNonNull) // should not compile because string cannot be null
let fooNull: string | null = "foo";
foo(fooNull) // should compile
Дополнительный вопрос для принятия undefined: stackoverflow.com/questions/78511231/…
Нулевой означает «нулевой или неопределенный», поэтому он нулевой. Здесь вам просто нужен ноль. Пожалуйста, отредактируйте, заменив «нулевой» на «нулевой». Или я сделаю это, когда у меня будет возможность.






Проверка того, расширяет ли союз T | null тип T, создает ли требуемое поведение:
type Null<T> = T | null extends T ? T : never;
function foo<T>(val: Null<T>) { console.info(val); }
let fooNonNull: string = "foo"
foo(fooNonNull); // Error
let fooNull: string | null = Math.random() > .5 ? "foo" : null;
foo(fooNull) // OK
Обратите внимание, что мне пришлось включить случайный фактор в инициализацию переменной fooNull, чтобы TypeScript не сузил параметр до string.
Нельзя ли это упростить до null extends T ...?
@jcalz Не могли бы вы привести мне пример T, где null extends T дает неправильный вывод? Мне очень трудно придумать случай, когда null extends T не приведет к тому же результату, что и T | null extends T, потому что, естественно, каждый тип можно присвоить самому себе.
Хм, я проверил, и это работает. Определенно бывают случаи, когда вывод не работает таким образом: если вы напишете function f<T>(ft: F<T>) {} и вызовете f(x), компилятор не всегда будет делать вывод, что T будет typeof x, а затем проверять это T extends F<T>. Если F является условным типом, я получаю хорошие результаты для T в проверочной позиции (например, T extends ...) по сравнению с T в другом месте (например, null extends T). Но поскольку я не могу воспроизвести это здесь, я просто удалю свой комментарий и сделаю это, если когда-нибудь найду его.
Что-то вроде
function foo<T>(x: T | null extends T ? T : never) { }должно помочь.