Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to fix "Index signature is missing in type" error?

Tags:

typescript

How can I fix the following type error?

Argument of type 'Query' is not assignable to parameter of type 'Input'. Index signature is missing in type 'Query'.(2345)

I am using the Input type as a generic type (catch-all) for query strings. When I feed an input of type Query, the error is thrown but the underlying JavaScript code runs just fine.

TypeScript Playground

interface Query {
    lorem: "0" | "1"
    ipsum: string
}

const query: Query = {
    lorem: "0",
    ipsum: "Hello world"
}

interface Input {
    [key: string]: string
}

const test = (input: Input) => {
    return input["lorem"]
}

test(query)
like image 236
sunknudsen Avatar asked Mar 15 '20 20:03

sunknudsen


People also ask

Does not satisfy the constraint index signature is missing in type?

The error "Index signature for type is missing in type" occurs when TypeScript doesn't consider a type that uses an index signature and a more specific type to be compatible. To solve the error, use the spread syntax (...) when calling the function, e.g. accessEmployee({... employee}); .

What is an index signature typescript?

In typescript, Index Signature identifies key type for indexing of an object. Everytime an object in typescript is created and indexing is expected on that object then developers must specify Index Signature .

Is incompatible with index signature?

The error "Property is incompatible with index signature" occurs when a property is not compatible with the specified type of the index signature. To solve the error, change the type of the property or use a union to update the type in the index signature.

Should I use type or interface typescript?

Interfaces are most recommended for defining new objects or methods or properties of an object where it will receive a specific component. Hence interface works better when using objects and method objects. Therefore it is our choice to choose between types or interface according to the program needs.

What are some examples of index signatures?

Here are a few examples of index signatures. The string type is the key, the value can be a string, number, or boolean: Options interface also has a field timeout, which works fine near the index signature. The key of the index signature can only be a string, number, or symbol. Other types are not allowed:

Is it possible to use index signature for generic keys?

This behavior suggests that the index signature is meant to be generic in regards to keys. But you can use a union of string literals to describe the keys in a Record<Keys, Type>: The Record<Keys, Type> is meant to be specific in regards to keys. I recommend using the index signature to annotate generic objects, e.g. keys are string type.

How does the index signature work in typescript?

The index signature simply maps a key type to a value type, and that's all. If you don't make that mapping correct, the value type can deviate from the actual runtime data type. To make typing more accurate, mark the indexed value as string or undefined. Doing so, TypeScript becomes aware that the properties you access might not exist: // etc...

Is it possible to add a string to an index signature?

Property 'baseSalary' is incompatible with index signature. Type 'string' is not assignable to type 'number'. 2. Index signature syntax The syntax of an index signature is pretty simple and looks similar to the syntax of a property, but with one difference.


1 Answers

Solution 1: Use type instead of interface

That is because the type [key: string]: string is not compatible with your Query interface, the latter of which contains two allowed keys: lorem and ipsum, while the former contains any arbitrary string as key. This is an issue with TypeScript interfaces in general: a specific interface cannot be saved into a more generic interface.

However, a specific type can be saved into a more generic type, so a quick solution will be to simply convert your interface to types:

type Query = {
    lorem: "0" | "1"
    ipsum: string
}

const query: Query = {
    lorem: "0",
    ipsum: "Hello world"
}

type Input = {
    [key: string]: string
}

const test = (input: Input) => {
    return input["lorem"]
}

test(query)

Solution 2: Spread the variable when calling test()

An alternative solution will simply to keep the interfaces, but use ES6 object spread to deconstruct/spread the variable query before passing it into test(). By doing that, you will force TypeScript to recognize { ...query } as indexable.

This solution is smart but a bit hack-ish, because you have to probably add a comment in the code to explain why you can't just use test(query) instead of test({ ...query }):

interface Query {
    lorem: "0" | "1"
    ipsum: string
}

const query: Query = {
    lorem: "0",
    ipsum: "Hello world"
}

interface Input {
    [key: string]: string
}

const test = (input: Input) => {
    return input["lorem"]
}

test({ ...query })

There is an extended thread on discussion on TypeScript's GitHub repo: might be a good place to read a little more about it.

like image 136
Terry Avatar answered Oct 15 '22 11:10

Terry