“The eternal void is filled with infinite possibilities” ~ Laozi

Typescript Void npm

Void 🔮

If you’re a React library maintainer, you may have come across a case where you need to store a user-provided value.

const ref = useRef<Value | null>(null);

How do you check if the ref contains a value? You could check if ref.current is null, but the generic is provided by the user and null could be a valid value. One possible way is doing something like this.

const ref = useRef({
  // Keep track of value assignments.
  hasValue: false,
  maybeValue: null as Value | null,

function setValue(value) {
  // Set the value as present.
  ref.hasValue = true;
  ref.maybeValue = value;

function doSomething() {
  if (ref.hasValue) {
    // We need the nullish assertion.
    const value = ref.maybeValue!;
    // Do something...

This works, but is a bit verbose and since maybeValue can’t really be typed, you’ll need the non-null assertion (and disable the eslint warning!).

Alternatively, you may use Void as a new primitive value. Unlike null, users won’t be able to see or provide this type, so you’re sure there will be no conflicts.

import { Void } from "ts-void";

Thanks to some typescript wizardry, Void acts a a real primitive. It is both a value and a type, and it works with equality narrowing.

const ref = useRef<Value | Void>(Void);

function doSomething() {
  if (ref.current !== Void) {
    // Now ref.current is only of type "Value".

You may be wondering what to do if also the user uses this library and provides Void as a value. Well, for these cases you can use ts-void-2!

Jokes apart, the whole point is to make this type private and never expose it to the user, otherwise it’s just a new nullish value, and Javascript has enough of those!

The way to ensure this is to bundle ts-void inside your library, and not use it as a dependency. Even if the user use ts-void, your private Void type will be unique!


View Github