'How to check and narrow a type with isNull instead of isNonNullable in TypeScript
I would like to universally type guard entities before returning them from an API. I want to make sure that anything that is null | undefined throws an HttpStatus.NOT_FOUND and thus I wanted to do something like this:
export const entityOr404 = <T>(entity: T | undefined): NonNullable<T> => {
if (entity != null) {
throw new HttpException('Not Found', HttpStatus.NOT_FOUND)
}
return entity
}
But in this case, TypeScript cannot understand that entity is NonNullable when returning (Type 'T' is not assignable to type 'NonNullable<T>'.). I also don't want to use the non-null assertion because I'd have to disable the eslint rule for this line. So I thought of doing something like this instead:
const isNonNullable = <T>(
entity: T | null | undefined
): entity is NonNullable<T> => {
return entity != null
}
export const entityOr404 = <T>(entity: T | undefined): NonNullable<T> => {
if (!isNonNullable(entity)) {
throw new HttpException('Not Found', HttpStatus.NOT_FOUND)
}
return entity
}
What I don't like about this solution is that I have to negate it and I think it would be more clear to have isNull instead of !isNonNullable and thus I'd like to write something like:
type Nullable = undefined | null
const isNull = (entity: unknown): entity is Nullable => {
return entity == null
}
But then I'm of course back to TypeScript being confused and throwing Type 'T' is not assignable to type 'NonNullable<T>'. when trying to return the entity. Is there a way for me to express the isNonNullable as its opposite? Somehow let TypeScript know that if !isNull(entity) then entity is NonNullable?
Solution 1:[1]
An assertion is the way !
const isNonNullable = <T>(
entity: T | null | undefined
): entity is NonNullable<T> => {
return entity != null
}
function assertEntity<T,>(entity: T): asserts entity is NonNullable<T> {
if (isNonNullable(entity != null)) {
throw new Error('My Error')
}
}
const entityOr404 = <T>(entity: T): NonNullable<T> => {
assertEntity(entity)
return entity
};
entityOr404(null) // never
entityOr404(5) // number
entityOr404({}) // object
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Matthieu Riegler |
