It is fairly common to have methods where one or more parameter can be null
or undefined
(or often both with derived types). This can make for really long method signatures in some cases:
doThing(
user: User | undefined | null,
thing: Thing | undefined | null,
...moreArgs
): Result {
// ...
}
I'm aware of a few ways to try to solve this problem, but both have downsides.
Optional parameters are great if the argument is truly optional, but feel awkward when the passed object can be null
.
This is shorter but just looks wrong to me:
doThing(user?: User | null, thing?: Thing | null, ...moreArgs)
The other way I know to fix this is with a generic:
type Nullable<T> = T | null | undefined
doThing(user: Nullable<User>, thing: Nullable<Thing>)
This is reasonable but I find that projects often end up with more than one generic of this type defined, they get imported from third party libraries, derived types end up having a trail of Maybe<T>
, Nullable<T>
, etc. Trying to keep this use standard across a large project can be really hard.
This seems like such a common use case that I would expect a more consistent solution. Is there a better way to do this?