Skip to content

Instantly share code, notes, and snippets.

@danieldietrich
Last active October 18, 2022 12:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danieldietrich/ee3c220652e87efbfc07774bea0807bb to your computer and use it in GitHub Desktop.
Save danieldietrich/ee3c220652e87efbfc07774bea0807bb to your computer and use it in GitHub Desktop.
The case of IsEmpty<T> versus universal types any, unknown and never

IsEmpty<T>

A value of type T is defined to be empty, if

  • it is an array and has no elements
  • it is an object and has no properties

Handling of universal types

  • any can be seen as the union of all types. A union distributes in conditional types, so any may or may not be empty. true | false = boolean
  • never is the empty union, it also ditributes in conditional types and leads to the empty union, which is never.
  • unknown has a very special meaning, unknown is not a union. An unknown value could be empty or not, we don't know. I would say IsEmpty<unknown> := unknown.

Therefore we could define:

  • IsEmpty<any> := boolean
  • IsEmpty<unknown> := unknown
  • IsEmpty<never> := never

At the use-site this would lead to:

// false
type _is_any_definitely_empty = boolean extends true ? true : false;

// false
type _is_any_definitely_non_empty = boolean extends false ? true : false;

// false
type _is_unknown_definitely_empty = unknown extends true ? true : false;

// false
type _is_unknown_definitely_non_empty = unknown extends false ? true : false;

// true
type _is_never_definitely_empty = never extends true ? true : false;

// true
type _is_never_definitely_non_empty = never extends false ? true : false;

This will lead to problems. It implies that the universal types any, unknown and never need a special treatment at the use-site.

// for example like this ...
Or<IsUniversal<T>, IsEmpty<T>> extends true ? DoThis<T> : DoThat<T>

// ... or like this, depending on the application semantics
Or<Not<IsUniversal<T>>, IsEmpty<T>> extends true ? DoThis<T> : DoThat<T>

where

IsUniversal<T> := Or<Is<T, any>, Or<Is<T, unknown>, Is<T, never>>>;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment