Maybe a type in typescript
Depending on the case, it can be void
, undefined
, or ?
optional modifier for properties and parameters.
It's:
function foo(x : string) : number | void { // returns nothing}
void
and undefined
types are compatible, but there is some difference between them. The former is preferable for function return types, because the latter requires a function to have return
statement:
function foo(x : string) : number | undefined { return;}
Maybe
can be implemented with generic type. Explicit Nothing
type can be implemented with unique symbol:
const Nothing = Symbol('nothing');type Nothing = typeof Nothing;type Maybe<T> = T | Nothing;function foo(x : string) : Maybe<number> { return Nothing;}
Or a class (private fields can be used to prevent ducktyping):
abstract class Nothing { private tag = 'nothing'}type Maybe<T> = T | typeof Nothing;function foo(x : string) : Maybe<number> { return Nothing;}
Notice that class types designate class instance type and require to use typeof
when a class is referred.
Or an object (if duck typing can be desirable):
const Nothing: { tag: 'Nothing' } = { tag: 'Nothing' };type Nothing = typeof Nothing;type Maybe<T> = T | Nothing;function foo(x : string) : Maybe<number> { return Nothing;}
enum Nothing { Nothing = 'Nothing'}type Maybe<A> = A | Nothingtype MaybeNumber = Maybe<number>const isNothing = (m: MaybeNumber): m is Nothing => m === Nothing.Nothing const foo = (m: MaybeNumber) => { if (isNothing(m)) { return Nothing.Nothing } else { return m + 1 }}foo(1) // ✔️foo('Nothing') // ❌foo(Nothing.Nothing) // ✔️
or without using an enum
using a string literal type
const Nothing = '__nothing__'type Maybe<A> = A | Nothingtype MaybeNumber = Maybe<number>const isNothing = (m: MaybeNumber): m is Nothing => m === Nothing const foo = (m: MaybeNumber) => { if (isNothing(m)) { return Nothing } else { return m + 1 }}foo(1) // ✔️foo(Nothing) // ✔️foo('__nothing__') // ✔️
or with symbols
const nothing = Symbol('Nothing')type Nothing = typeof nothingtype Maybe<A> = A | Nothingtype MaybeNumber = Maybe<number>const isNothing = (m: MaybeNumber): m is Nothing => m.toString() === 'Symbol(Nothing)' const foo = (m: MaybeNumber) => { if (isNothing(m)) { return nothing } else { return m + 1 }}foo(1) // ✔️foo(nothing) // ✔️
live on stackblitz