TypeScript Data Types - Null, Void, Undefined, Never and Object
Tags: typescript, javascript, oop, beginners
Published: 2020-01-05 22:36:39

**Subscribe to my email list now at http://jauyeung.net/subscribe/**

**Follow me on Twitter at https://twitter.com/AuMayeung**

**Many more articles at https://medium.com/@hohanga**

JavaScript, like any other programming language, has its own data structures and types.

JavaScript has a few data types that we have to know, to build programs with it. Different pieces of data can be put together to build more complex data structures.

JavaScript is a loosely typed, or dynamically typed, language. This means that a variable that’s declared with one type can be converted to another type without explicitly converting the data to another type.

Variables can also contain any type at any time, depending on what’s assigned. With dynamically typed languages, it’s hard to determine the type that a variable has without logging it and we might assign data that we don’t want in the variable.

TypeScript rectifies these issues by letting us set fixed types for variables so that we’re sure of the types. In this article, we’ll look at the `void`, `null`, `undefined`, `never`, and the `object` types.

* * *

Void
====

The `void` type is pretty much the opposite of the `any` type. It means the absence of any type. So, the variable of the `void` type can only have the value `null` if the `--strictNullChecks` setting isn’t specified when running the TypeScrip compiler or it can be set to `undefined`.

Therefore, directly assigning values to a `void` variable isn’t very useful. It’s more used for specifying the return data type of a function. A function that has the `void` return type doesn’t return anything.

For example, we can do a useless assignment to a `void` variable like in the following code:

```typescript
let useless: void = undefined;
```

We can set the return type of an arrow function to `void` by writing:

```typescript
const voidFn = (): void => {  
  console.log("Void function returns nothing");  
}
voidFn();
```

Alternatively, we can set the return type to `void` for a traditional function like in the following code:

```typescript
function voidFn(): void {  
  console.log("Void function returns nothing");  
}
voidFn();
```

Both function calls will output `Void function returns nothing` from the `console.log` statement inside the function.

* * *

Null
====

The `null` type represents a variable that can only take on the value `null`. `null` means that there's no value for a variable.

So, once again, assigning a value to it is pretty useless. We can only assign `null` to a variable that has the variable `null`. With the `--strictNullChecks` flag set when running the TypeScript compiler, `null` can only be assignable to variables with the `any` type and the `null` type.

Where it does become useful is that we can have variables that can have values from more than one assigned to it with union types.

Then, we can specify something useful along with the `null` type. This is different from JavaScript in that the value `null` is the type `object` instead of `null` for historical reasons.

* * *

Undefined
=========

The `undefined` type represents a variable that can only take on the value `undefined`. So, once again, assigning a value to it is pretty useless.

We can only assign `undefined` to a variable that has the variable `null`. `undefined` can only be assignable to variables with the `any` type and the `undefined` type.

Where it does become useful is that we can have variables that can have values from more than one assigned to it with union types.

Then, we can specify something useful along with the `undefined` type. It’s practically useless on its own, so we shouldn’t see many cases with variables that have only the `undefined` type.

* * *

Never
=====

The `never` type is a type of value that represents something that never occurs. It’s like `void` in that it’s useful for designating that a function never returns anything.

The `never` type is a sub-type of, and is assignable to, every type. However, no type is a sub-type of, or assignable to, the `never` type except for other `never` variables.

A function that has a `never` return type must always have an unreachable endpoint. For example, we can write a function that has an infinite loop that has the `never` return type like in the following code:

```typescript
function infiniteFn(): never {  
  while (true) {  
  }  
}
```

A function that throws an exception may also have the `never` return type, like in the following example:

```typescript
function errorFn(message: string): never {  
  throw new Error(message);  
}
errorFn('Error occurred');
```

* * *

Object
======

The `object` type is a type that represents non-primitive objects. That is, anything that’s not a `number`, `string`, `boolean`, `bigint`, `symbol`, `null`, or `undefined`.

It’s mainly used in the type definition of the `Object` object in the standard library and other pieces of code that don’t want primitive values to be assigned to it, or passed into a function.

For example, in the type definition of the `Object.create` method, we see that the type of the parameter is set to the `object` like in the following code:

```typescript
create(o: object | null): any;
```

Likewise, in the signature of the `setPrototypeOf` method in the same type declaration, we see that the `proto` parameter, which is the parameter that takes the prototype of an object, also has the `object` type set, as it does below:

```typescript
setPrototypeOf(o: any, proto: object | null): any;
```

This way, we can’t pass in primitive values into these methods as arguments in TypeScript. If we did, then we would get an error. So, if we have the following code in our TypeScript files, then they would be compiled and run:

```typescript
const obj1 = Object.create({});      
const obj2 = Object.create(null);  
console.log(obj1);  
console.log(obj2);
```

We would get an empty object in both `console.log` statements.

The only difference is that `obj2` is a pure object, which means it doesn’t inherit from any prototype. Passing in primitive values to the `create` method like in the code below will cause compilation to fail:

```typescript
Object.create(42);   
Object.create("abc");   
Object.create(false);  
Object.create(undefined)
```

The code above would get us an `Argument of type ‘42’ is not assignable to parameter of type ‘object | null’` error for the first one, `Argument of type ‘abc’ is not assignable to parameter of type ‘object | null’` for the second one.

The third line would get us `Argument of type ‘false’ is not assignable to parameter of type ‘object | null’`, and the last line would get us `Argument of type ‘undefined’ is not assignable to parameter of type ‘object | null’`.

Compilation would fail and the code wouldn’t run.

Also, we can use it to prevent primitive values from being assigned to it. For example, if we write:

```typescript
let x: object = {};
```

Then, the code above would be compiled and run. However, if we write the following instead:

```typescript
let x: object = 1;
```

Then we get `Type ‘1’ is not assignable to type ‘object’` and the code can’t be compiled with the TypeScript compiler and be run, since `1` is a primitive value.

The `void` type is pretty much the opposite of the `any` type. It means the absence of any type. So, the variable of the `void` type can only have the value `null` if the `--strictNullChecks` setting isn’t specified when running the TypeScrip compiler or it can be set to `undefined`.

It’s useful for declaring functions that don’t return anything and not much else. The `null` type variable can only take on the `null` value. The `undefined` type can only be assigned the value `undefined`.

The `object` type is a type that represents non-primitive objects. That is, anything that’s not a `number`, `string`, `boolean`, `bigint`, `symbol`, `null`, or `undefined`.

It’s mainly used in the type definition of the `Object` object in the standard library and other pieces of code that don’t want primitive values to be assigned to it, or passed into a function.