Beginner's TypeScript #22
Tags: programming, beginners, typescript
Published: 2024-01-14 15:00:00

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/annyrov9f6r23had5gfu.png)

⭐ **Error Message: "Types Of Property Are Incompatible"** ⭐

We have a **routingConfig **object which contains some routes. These routes are an array of objects, each with a **path** and a **component** property, both of which are expected to be **strings**:

```ts
const routingConfig = {
  routes: [
    {
      path: "home",
      component: "HomeComponent",
    },
    {
      path: "about",
      component: "AboutComponent",
    },
    {
      path: "contact",
      component: "ContactComponent",
    },
  ],
}
```

We also have a **createRoutes** function that takes this **routingConfig**, and maps it into a type:

```ts
const createRoutes = (config: {
	routes: {
		path: string;
		component: string;
	}[];
}) => {};
```

When calling **createRoutes** with the **routingConfig**, we get a large error message:

```ts
createRoutes(routingConfig); // red squiggly line under routingConfig

// hovering over routingConfig shows:
Argument of type '{ routes: { path: string; component: string | number; }[]; }' is not assignable to parameter of type '{ routes: { path: string; component: string; }[]; }'.
  Types of property 'routes' are incompatible.
    Type '{ path: string; component: string | number; }[]' is not assignable to type '{ path: string; component: string; }[]'.
      Type '{ path: string; component: string | number; }' is not assignable to type '{ path: string; component: string; }'.
        Types of property 'component' are incompatible.
          Type 'string | number' is not assignable to type 'string'.
            Type 'number' is not assignable to type 'string'.
```

We will figure out what this error is telling us, and make the error more readable.

We have a large error message that was difficult to understand:

```bash
Argument of type '{ routes: { path: string; component: string | number; }[]; }' is not assignable to parameter of type '{ routes: { path: string; component: string; }[]; }'.

Types of property 'routes' are incompatible.

Type '{ path: string; component: string | number; }[]' is not assignable to type '{ path: string; component: string; }[]'.

Type '{ path: string; component: string | number; }' is not assignable to type '{ path: string; component: string; }'.

Types of property 'component' are incompatible.

Type 'string | number' is not assignable to type 'string'.

Type 'number' is not assignable to type 'string'.
```

The first line tells us that when we pass the **routingConfig** object into the **createRoutes** function, the shape of the object is not compatible with the shape of the parameter.

Next, we see that the **routes** are incompatible.

Continuing on, we can see that a union of **string | number** is trying to be assigned to just **string**.

Finally, we see that **number** is not assignable to **string**.

Usually, when faced with a large error message like this, it is a good idea to start from the bottom.

Since we have a **number** being passed into a slot that expects a **string**, we can scan upwards to identify the property that is causing the issue. In this case, it is the **component** property.

Inside of the **routes** array, the **about** path's component property is **12** instead of a string:

```ts
const routingConfig = {
	routes: [
		{
			path: "home",
			component: "HomeComponent",
		},
		{
			path: "about",
			component: 12, // Error occurs here
		},
		{
			path: "contact",
			component: "ContactComponent",
		},
	],
}
```

Now, we know what is causing the error and even have some ideas about how to fix it, but we still need to clean up the error message.

👉 **Solution**

There are a few ways to make the error readable and informative:

1️⃣ **Pass the Object Inline**

One way to make the error message better is instead of declaring **routingConfig** as a separate object, pass it inline:

```ts
createRoutes({
	routes: [
		{
			path: "home",
			component: "HomeComponent",
		},
		{
			path: "about",
			component: 12, // Error occurs here
		},
		{
			path: "contact",
			component: "ContactComponent",
		},
	],
})
```

This lets TypeScript make better assumptions about the object, resulting in a more relevant error message.

Hovering over **createRoutes **shows us the shape:

```ts
const createRoutes: (config: {
	routes: {
		path: string;
		component: string;
	}[];
}) => void;
```

Now there will be an error underlining the component where the error occurs:

```ts
...
{
    path: "about",
    component: 12,  // red squiggly line under component
},
...
```

Hovering over **component** to see the error message, it is more clear:

```bash
Type 'number' is not assignable to type 'string'.

The expected type comes from property 'component' which is declared here on type '{ path: string; component: string; }'
```

Having the separate **routingConfig** object does not give us nice error messages because TypeScript is not sure if we will be using it in a different scenario elsewhere in the code.

2️⃣ **Use Type Annotations**

Assigning explicit type annotations to the objects also will help TypeScript deliver a more concrete error message.

First, create a new **RoutingConfig** type, then use it as the config type for the **createRoutes** function:

```ts
type RoutingConfig = {
	routes: {
		path: string;
		component: string;
	}[];
};

const createRoutes = (config: RoutingConfig) => {};
```

Then we can also annotate the **routingConfig** object:

```ts
const routingConfig: RoutingConfig = {
	routes: [
		{
			path: "home",
			component: "HomeComponent",
		},
		{
			path: "about",
			component: "AboutComponent",
		},
		{
			path: "contact",
			component: "ContactComponent",
		},
	],
}
```

Again, this will give us a more relevant error message inside of **routingConfig**.

3️⃣ **Use the satisfies Keyword**

Finally, we could use the **satifies** keyword on the **routingConfig** object to specify it as a **RoutingConfig** type:

```ts
const routingConfig: RoutingConfig = {
	routes: [
		{
			path: "home",
			component: "HomeComponent",
		},
		{
			path: "about",
			component: 12, // red squiggly line under component
		},
		{
			path: "contact",
			component: "ContactComponent",
		},
	],
} satisfies RoutingConfig;
```

All of these strategies are great for getting TypeScript to provide more useful error messages.

---

I hope you found it useful. Thanks for reading. 🙏

Let's get connected! You can find me on:
- **Medium:** https://medium.com/@nhannguyendevjs/
- **Dev**: https://dev.to/nhannguyendevjs/
- **Hashnode**: [https://nhannguyen.hashnode.dev](https://nhannguyen.hashnode.dev/)/
- **Linkedin:** https://www.linkedin.com/in/nhannguyendevjs/
- **X (formerly Twitter)**: https://twitter.com/nhannguyendevjs/
- **Buy Me a Coffee:** [https://www.buymeacoffee.com/nhannguyendevjs/](https://www.buymeacoffee.com/nhannguyendevjs/)