Reputation: 1023
I'm trying to return an array containing an initialized object and a number.
However I get the following error:
Property 'foo' does not exist on type 'number | IObj' Property 'foo' does not exist on type 'number'
interface IObj {
[k: string]: string
}
function test(fields: string[]){
const foo: IObj = {}
fields.forEach((x) => foo[x] = 'baz')
return [foo, 1]
}
const [foo, x] = test(['foo'])
foo.foo
How can I fix this ?
Upvotes: 1
Views: 561
Reputation: 249506
For array literals by default typescript will infer an array, so when destructuring occurs each element will be IObj | number
, the information that the first element is IObj
and the second is a number will be lost.
In 3.4, recently released you can use as const
to get the compiler to infer a readonly tuple (return [foo, 1] as const
)
Or you can use an explicit type annotation to tell the compiler you want a tuple:
interface IObj {
[k: string]: string
}
function test(fields: string[]) : [IObj, number]{
const foo: IObj = {}
fields.forEach((x) => foo[x] = 'baz')
return [foo, 1]
}
const [foo, x] = test(['foo'])
foo.foo
If you are going to use constants for the fields
parameter, might I suggest a more type safe version of your code:
function test<K extends string>(fields: K[]) : [Record<K, string>, number]{
const foo = {} as Record<K, string>
fields.forEach((x) => foo[x] = 'baz')
return [foo, 1]
}
const [foo, x] = test(['foo'])
foo.foo //ok
foo.foo2 // err
Upvotes: 1