10

I'm trying to do the following:

interface Collection {
   foo: string,
   bar: string
}

const patchCollection = (
    collection: Collection, 
    propertyToUpdate: {[key: keyof Collection]: any}
) => {
    // do something here
}

The goal would be to have key: "foo" | "bar" but I get the following error:

An index signature parameter type cannot be a literal type or generic type. Consider using a mapped object type instead

But I'm not sure how a mapped object would apply here. Any help? Thanks!


EDIT:

The question got close due to similar questions existing. I tried the solutions provided there but I didn't manage to make it work with the Mapped type. However, I was able to solve my issue with The Partial Utility Type (https://www.typescriptlang.org/docs/handbook/utility-types.html#partialtype )

interface Collection {
   foo: string,
   bar: string
}

const patchCollection = (
    collection: Collection, 
    propertyToUpdate: Partial<Collection>
) => {
    // do something here
}

This solves also the issue of having the right value type associated with the right key (which I didn't address previously). I'm not sure if I was using the Mapped and Index types in the wrong way (and if there is a way to achieve it with those), but Partial definitely seems like the right approach I should have taken from the beginning.

Francesco Bianchi
  • 772
  • 1
  • 4
  • 13
  • 1
    Look [here](https://www.typescriptlang.org/docs/handbook/2/mapped-types.html): *"Mapped types build on the syntax for index signatures, which are used to declare the types of properties which have not been declared ahead of time."* – Robert Harvey Feb 11 '22 at 17:15
  • 1
    You could use Record: propertyToUpdate: Record – Sergio Loaiza Dec 28 '22 at 23:02
  • Now that the question is open, perhaps you could shift your answer to the answer section. – Rohit Gupta Apr 07 '23 at 05:44

1 Answers1

6

Use a mapped type (notice the in keyword)

interface Collection {
   foo: string,
   bar: string
}

const patchCollection = (
    collection: Collection, 
    propertyToUpdate: {[key in keyof Collection]: any}
) => {
    // do something here
}

A mapped type is a generic type which uses a union of PropertyKeys (frequently created via a keyof) to iterate through keys to create a type.

docs: https://www.typescriptlang.org/docs/handbook/2/mapped-types.html

Hinrich
  • 13,485
  • 7
  • 43
  • 66