Nicolò Andronio

Nicolò Andronio

Full-stack developer, computer scientist, engineer
Evil Genius in the spare time

TypeScript odd types: unknown, void, never, any, null and undefined

TypeScript has a very complex and powerful type systems. Yet for some it also constitutes a mystery in its more deep features. Among these, special types can be source of brain freezes for many, so let’s see in detail what they all mean.

Void

The void type represents the absence of any type. It is notably used to describe the return value of functions that do not return anything. No value can be assigned to a variable of type void, except for undefined. Additionally, if you do not have the --strictNullChecks option enabled on your TypeScript compiler, you can in principle also assign null to void variables. However, I highly advised you avoid that and always have --strictNullChecks enabled, as it enforces a more secure and predictable application behaviour. Besides, it allows you to worry less on whether or not you should check for nullity.

Any

At the opposing end of the spectrum is the any type, which represents literally any type. A variable whose type is any can be assigned any possible value and it will never produce a compilation error. Similarly, a function that returns any can return arbitrary objects, atomic values or even nothing, and will still be valid. Additionally, you can always access arbitrary properties and methods from a variable of any type without the compiler complaining. On the downside, you have no guarantee that the actual value contained there at runtime will abide to your expectations. Working with any is occasionally unavoidable, especially when dealing with libraries written in pure javascript or with native bindings. At the same time, I discourage sweeping warnings under the rug. If possible, get type definition for third party libraries from typing repositories like DefinitelyTyped or write your type declarations yourself.

Unknown

The unknown type is similar to any, in that it also represents a type that is apriori not known. However, it behaves slightly differently than any:

unknown is safer to usa than any, since it restricts all operations you can perform on variables and return values. I also like to think of unknown as “I don’t care what type it is” and find it especially useful for defining callbacks. Using it for declaring callbacks is one of my favourite usages:

Never

The never type is very interesting. It represents the type of values that can never occur. While in principle it may make little sense, it does have many interesting application:

Null and undefined

Null and undefined are singleton types. null is the type of the singleton value null, and undefined is type type of single value undefined. Duh. If you have the --strictNullChecks compiler option enabled (as you should), they can only be assigned to unknown or any directly. Otherwise, you need to specify that your values may accept either of those special symbols by using a union type.