TypeScript Error: Index from Union Type — Solution for Beginners

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction: Why is TypeScript Complaining About Your Code?

\n\n

Have you ever written TypeScript code that seems perfectly logical, but the compiler suddenly throws a frightening error? If you've encountered the message "An index signature parameter type cannot be a union type. Consider using a mapped object type instead" — you are not alone. This error is one of the most popular questions on Stack Overflow (thousands of views!), and it often stumps even experienced developers.

\n\n

In this article, we won't just show you how to fix the error. We'll break down why TypeScript is so strict, and how to use mapped object types to make your code not only functional but also safer. Let's go!

\n\n

What is an Index Signature and Why Do You Need It?

\n\n

Imagine you are creating an object where the keys are strings and the values are numbers. For example, a dictionary of product prices:

\n\n
// Regular object\nconst prices = {\n  apple: 100,\n  banana: 50,\n  cherry: 200\n};
\n\n

But what if you want to tell TypeScript: "Hey, this object can have any string keys, and all values will be numbers"? That's where the index signature comes in — a special syntax that describes a pattern for all properties of an object:

\n\n
// Index signature: [key: string]: number\ninterface PriceMap {\n  [key: string]: number;\n}\n\nconst prices: PriceMap = {\n  apple: 100,\n  banana: 50\n};
\n\n

Here, [key: string]: number is the index signature. It says: "Keys are strings, values are numbers." Simple, right?

\n\n

So What's the Problem with Union Types?

\n\n

Now imagine you want to restrict the possible keys to just two options: 'name' or 'age'. It seems logical to write this:

\n\n
// ❌ ERROR! This is not allowed\ninterface Person {\n  [key: 'name' | 'age']: string | number;\n}
\n\n

And then TypeScript throws that very error: "An index signature parameter type cannot be a union type. Consider using a mapped object type instead".

\n\n

Why? Because the index signature is meant to describe an unlimited set of keys. If you want to specify a specific list of keys, that's no longer a pattern, but an exact description of the structure. TypeScript doesn't allow mixing these concepts.

\n\n

How to Fix the Error? Use Mapped Object Type

\n\n

The solution that the compiler itself suggests is to use a mapped object type. It sounds complicated, but in reality, it's just a way to "iterate" over all keys from a union type and create a property for each one.

\n\n

Here's what it looks like:

\n\n
// ✅ CORRECT: using mapped type\ntype Person = {\n  [K in 'name' | 'age']: K extends 'name' ? string : number;\n};\n\n// Or a simpler version if the value types are the same:\ntype PersonSimple = {\n  [K in 'name' | 'age']: string | number;\n};
\n\n

Let's break down the syntax [K in 'name' | 'age']:

\n
    \n
  • K — is a variable that takes each value from the union type one by one ('name', then 'age').
  • \n
  • in — is a keyword that starts a "loop" over the types.
  • \n
  • 'name' | 'age' — is our set of keys.
  • \n
\n\n

As a result, TypeScript will create an object with two specific properties: name and age. The error is gone!

\n\n

Example with Different Value Types

\n\n

It's often the case that different keys should have different value types. Using conditional types, this can be solved elegantly:

\n\n
type Config = {\n  [K in 'host' | 'port' | 'debug']: \n    K extends 'host' ? string :\n    K extends 'port' ? number :\n    boolean;\n};\n\n// Now:                

Blogs

Book Recommendations