Type Operators (keyof and typeof) in TypeScript
Tags: typescript, javascript, programming, beginners
Published: 2023-04-16 12:06:30

Have you ever heard `typeof` operator?
I guess 99% of readers will say "yes".
However, do you really understand the difference of `typeof` between in TypeScript and JavaScript?
If you are not confident, no worries! This article is for you!
I am going to explain how to use Type Operators, keyof and typeof, in this article.

## Type Operators
### keyof operator
You may sometimes be tired of writing types. For example, here is an example:

```ts
const createPerson = (id: number, name: string, age: number) => {
  return {
    id,
    name,
    age
  };
};

interface Person {
  id: number;
  name: string;
  age: number;
}

const showPersonsProperty = (person: Person, key: "id" | "name" | "age") => {
  console.log("This person's " + key + " is " + person[key] + ".")
};

const person1 = createPerson(1234, "John", 20);

showPersonsProperty(person1, "name");
// [LOG]: "This person's name is John"

showPersonsProperty(person1, "age");
// [LOG]: "This person's age is 20."
```
The above code is functional. But how did you feel about this?

Actually, we can make this code more concise by utilizing type operators!

We (and TypeScript's type checker) already know the possible argument to be passed to the "key" parameter when defining the `Person` interface.

If so, why don't we use this `Person` interface to get its keys?
Let me show the updated code.
```ts
const createPerson = (id: number, name: string, age: number) => {
  return {
    id,
    name,
    age
  };
};

interface Person {
  id: number;
  name: string;
  age: number;
}

const showPersonsProperty = (person: Person, key: keyof Person) => {
  console.log("This person's " + key + " is " + person[key] + ".");
};

const person1 = createPerson(1234, "John", 20);

showPersonsProperty(person1, "name");
// [LOG]: "This person's name is John"

showPersonsProperty(person1, "age");
// [LOG]: "This person's age is 20."
```
In this updated code, we could refer to the keys of the `Person` interface instead of giving union type (`"id" | "name" | "age"`) to the key parameter.
The `keyof` operator generates a union type from keys of Object Type (Interface). In the former example codes, `"id" | "name" | "age"` and `keyof Person` have the same meaning.
This technique will help your life when an object has tons of properties!

### typeof operator
Next, what if a person object is declared manually, like the below code?
```ts
const person1 = {
  id: 4321,
  name: "Mike",
  age: 35
};

interface Person {
  id: number;
  name: string;
  age: number;
}

const showPersonsProperty = (person: Person, key: keyof Person) => {
  console.log("This person's " + key + " is " + person[key] + ".");
};

showPersonsProperty(person1, "name");
// [LOG]: "This person's name is Mike."

showPersonsProperty(person1, "age");
// [LOG]: "This person's age is 35."
```
Hmm... This code works okay. But we can write simpler code by utilizing `typeof` operator.
Here is an example.
```ts
const person1 = {
  id: 4321,
  name: "Mike",
  age: 35
};

const showPersonsProperty = (person: typeof person1, key: keyof typeof person1) => {
  console.log("This person's " + key + " is " + person[key] + ".");
};

showPersonsProperty(person1, "name");
// [LOG]: "This person's name is Mike."

showPersonsProperty(person1, "age");
// [LOG]: "This person's age is 35."
```
Perfect! We could skip defining the `Person` interface by referring to the `person1` object.
You can use `typeof` to retrieve the type of a value. (Please keep in mind that this typeof is the operator provided by TypeScript. It means this operator does not exist in runtime.)

### keyof typeof
You might wonder what is `keyof typeof`. Good question!
Let me explain this advanced technique.
By chaining these two operators, you can retrieve the keys of an object variable as Union type.

First, the Object type is retrieved by `typeof objectVariable`. Second, keys of the Object type are extracted by the `keyof` operator. Finally, these keys will be a literal union type.

By using the type operators, we will be able to write more concise code!