I want to implement a universal type guard for entities returned from an API. The goal is to handle any null | undefined
values by throwing an HttpStatus.NOT_FOUND
error. Initially, I tried the following approach:
export const entityOr404 = <T>(entity: T | undefined): NonNullable<T> => {
if (entity != null) {
throw new HttpException('Not Found', HttpStatus.NOT_FOUND)
}
return entity
}
However, TypeScript raised an error (
Type 'T' is not assignable to type 'NonNullable<T>'.
) because it couldn't recognize that entity was NonNullable in the return statement. To address this issue, I came up with a different solution:
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
}
Although this solution works, I find having to negate the function cumbersome. I believe having a isNull
function instead of !isNonNullable
would be clearer. So, I attempted the following modification:
type Nullable = undefined | null
const isNull = (entity: unknown): entity is Nullable => {
return entity == null
}
Unfortunately, this led to TypeScript complaining again with the same error message (
Type 'T' is not assignable to type 'NonNullable<T>'.
). Is there a way to express the opposite of isNonNullable
and help TypeScript understand that if !isNull(entity)
, then entity is NonNullable?