0

I would like to ask why the compiler doesn't let me use the callback function to forEach although as far as I know "a" | "b" | "c" | "d" is a subtype of string. Please check out the error message after the code block. I guess I could solve this problem with a Record type, correct? Thanks!

const obj = { a: 10, b: 20, c: 30, d: 40 }
type O = typeof obj

Object.keys(obj).forEach((value: keyof O) => {
  console.log(value)
})

error TS2345: Argument of type '(value: "a" | "b" | "c" | "d") => void' is not assignable to parameter of type '(value: string, index: number, array: string[]) => void'.
Types of parameters 'value' and 'value' are incompatible.
Type 'string' is not assignable to type '"a" | "b" | "c" | "d"'.

Take
  • 324
  • 3
  • 10
  • Possible duplicate of [TypeScript: Object.keys return string\[\]](https://stackoverflow.com/questions/52856496/typescript-object-keys-return-string) – jcalz Jan 29 '20 at 15:21

1 Answers1

3

I managed to get this to work with:

(Object.keys(obj) as (keyof O)[]).forEach((value: keyof O) => {
  console.log(value)
})

The problem stems from Object.keys, which will return a string[] no matter what.

Using this method isn't really safe though; when I tested this, the compiler wasn't able to determine whether or not obj actually had keys which conform to keyof O

OliverRadini
  • 6,238
  • 1
  • 21
  • 46
  • 1
    Oh I see, I had the *assignability* backwards. I have to give my callback a supertype and not a subtype as parameter, meaning at least `string`, because this is what `Object.keys` returns. – Take Jan 29 '20 at 15:21