With array literals in typescript, the default behavior is for types to be inferred, resulting in each element being of type IObj | number
. This means that the specific information regarding the first element being of type IObj
and the second being a number gets lost during destructuring.
In the recently released version 3.4, you can use as const
to instruct the compiler to infer a readonly tuple (return [foo, 1] as const
)
Alternatively, you can provide an explicit type annotation to specify that you intend to have 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 plan to use constants for the fields
parameter, consider using a more type-safe approach like this:
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