I'd like to use an array to iterate through interface properties, however it's throwing a ts compile error on the forEach function:
interface A {
foo: string
bar: string
baz: string
}
function fn(obj: A) {
;["foo", "bar"].forEach( (prop: keyof A) => {
obj[prop] // do stuff
})
}
The error:
Argument of type '(prop: keyof A) => void' is not assignable to parameter of type '(value: string, index: number, array: string[]) => void'. Types of parameters 'prop' and 'value' are incompatible. Type 'string' is not assignable to type 'keyof A'
Something like this would work, but it feels redundant:
function fn(obj: A) {
const ar: (keyof A)[] = ["foo", "bar"]
ar.forEach( (prop: keyof A) => {
obj[prop] // do stuff
})
}
CodePudding user response:
TypeScript infers the type of ["foo", "bar"]
to be string[]
, which can't be assigned to type keyof A
because it could contain strings that aren't in that type. If you tell TypeScript that your array is of type (keyof A)[]
then it works. For example:
interface A {
foo: string
bar: string
baz: string
}
function fn(obj: A) {
;(["foo", "bar"] as (keyof A)[]).forEach( (prop) => {
obj[prop] // do stuff
})
}
That example uses a type assertion, though, which it's preferrable to avoid when possible as it bypasses TypeScript's type checking. You can avoid that by using something like this instead, which will refuse to compile if you attempt to put a string in your array that isn't one of A
's property names:
interface A {
foo: string
bar: string
baz: string
}
function fn(obj: A) {
let values: (keyof A)[] = ['foo', 'bar'];
values.forEach( (prop) => {
obj[prop] // do stuff
})
}