---
id: 67d3018062fe6ba92b7d8299
title: How Do the Different Types Work in TypeScript?
challengeType: 19
dashedName: how-do-the-different-types-work-in-typescript
---

# --description--

You've already seen one in the previous lesson: `string[]`, which represents an array of strings. But how does that actually work?

For the primitive data types `string`, `null`, `undefined`, `number`, `boolean`, and `bigint`, TypeScript offers corresponding type keywords. In our example, we are using these types to annotate our variables:

```js
let str: string = "Naomi";
let num: number = 42;
let bool: boolean = true;
let nope: null = null;
let nada: undefined = undefined;
```

Now, we have explicitly declared `str` as `string` - which might seem confusing because we assigned it a string value already, but this annotation ensures that we cannot reassign a different value type (like a number) to that variable.

But what about arrays and objects? Well, you've already seen the syntax for an array! You can define an array of specific type with two different syntaxes:

```js
const arrOne: string[] = ["Naomi"];
const arrTwo: Array<string> = ["Camperchan"];
```

Fundamentally, these two syntaxes are the same, and the choice between the two is generally a matter of preference.

Objects get a bit more complicated. You can define the exact structure of an object:

```js
const obj: { a: string, b: number } = { a: "Naomi", b: 42 };
```

This syntax means that property `a` must always be a string, property `b` must always be a number, and you cannot add or remove properties.

But maybe you don't want to restrict the properties? Maybe you want an object with any keys, but the values all need to be strings. There are two ways you can do this:

```js
const objOne: Record<string, string> = {};
const objTwo: { [key: string]: string } = {};
```

Like the array types, these are fundamentally similar. With these object types, you must define both the type of the keys and the type of the values. Keys must always be strings, but you can define custom string types to further restrict those keys.

In addition to these types, TypeScript offers four other helpful types. The first is `any`, which indicates that a value can have any type. This is effectively the Konami Code of TypeScript - it tells the compiler to stop caring about the type of that variable and let you do whatever.

The second is `unknown`, which is generally preferred over `any`. The `unknown` type tells TypeScript that you do care about the type of the value, but you don't actually know what it is. If you then try to perform type-specific actions (like a subtraction operator, or the `slice()` method to perform a specific string operation), TypeScript will expect you to narrow down the type of that value first. You'll learn more about type narrowing in an upcoming lesson.

The third is `void`. This is a special type that you'll typically only use when defining functions. It's effectively the opposite of `any` - it represents the absence of any type at all. Functions which don't have a return value, such as `console.log()`, have a return type of `void`.

Finally, there is the `never` type. This is probably something you won't use often - it represents a type that will never exist. For example, passing a mock object to a function in your test suite might be a good use of `never` to indicate that such an object would never really be passed to the function.

Expanding on these types, you have access to the `type` keyword. This keyword is like `const`, but instead of declaring a variable you can declare a type:

```js
type myString = string;
```

This might not seem terribly useful on its own, but when coupled with union types it becomes powerful. A union type allows you to combine two or more types into one. Here's an example:

```js
type stringOrNumber = string | number;
```

Our `stringOrNumber` type matches values that are a string and values that are a number. You can then combine your type with other types, like an array:

```js
const stuff: stringOrNumber[] = ["a", 2, "c", 1000];
```

You can also define more strict types that include only specific values:

```js
type bot = "camperchan" | "camperbot" | "naomi";
type digit = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
```

You could then combine those types to create more specific restrictions on an object:

```js
const artificialIntelligence: Record<bot, digit> = { camperchan: 5 }
```

Though if you need more control over the structure of an object, chances are you'll reach for our final type: `interface`. Interfaces are effectively classes, but for types. They can implement or extend other interfaces, are specifically object types, and are generally preferred unless you need a specific feature offered by a type declaration.

```js
interface wowie {
  zowie: boolean;
  method: () => void;
}
```

Finally, functions can also be given type signatures. In the previous lesson, you saw how to define the type of a particular parameter:

```js
const getRandomValue = (array: string[]) => {
  return array[Math.floor(Math.random() * array.length)];
}
```

But you can also define the return type of the function.

```js
const getRandomValue = (array: string[]): string => {
  return array[Math.floor(Math.random() * array.length)];
}
```

In this example, we've told TypeScript that the function should return a string. If we try to return anything else, TypeScript will provide a compiler error to let us know.

And that covers the basics of TypeScript's type system. It's pretty complex, and has a lot of moving parts, but it can often help to think of it as mirroring JavaScript's types.

# --questions--

## --text--

Which of the following is NOT a primitive data type in TypeScript?

## --answers--

`string`

### --feedback--

Primitive data types are the most basic data types available in TypeScript.

---

`number`

### --feedback--

Primitive data types are the most basic data types available in TypeScript.

---

`boolean`

### --feedback--

Primitive data types are the most basic data types available in TypeScript.

---

`array`

## --video-solution--

4

## --text--

What is the purpose of the `unknown` type in TypeScript?

## --answers--

It allows any type of value to be assigned without type checking.

### --feedback--

Unlike `any`, `unknown` requires type narrowing before specific operations can be performed.

---

It indicates that you don't know the type and need to narrow it before use.

---

It represents the absence of any type at all.

### --feedback--

Unlike `any`, `unknown` requires type narrowing before specific operations can be performed.

---

It represents a type that will never exist.

### --feedback--

Unlike `any`, `unknown` requires type narrowing before specific operations can be performed.

## --video-solution--

2

## --text--

Which keyword is used to declare a custom type in TypeScript?

## --answers--

`interface`

### --feedback--

This keyword is used to define a contract for object shapes, not to declare custom types.

---

`type`

---

`custom`

### --feedback--

This is not a valid keyword in TypeScript.

---

`define`

### --feedback--

This is not a valid keyword in TypeScript.

## --video-solution--

2
