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)
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}); .
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 .
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.
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.
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:
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.
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...
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.
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)
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With