I tried to restructure the type of the read-only array, but it didn't work:
const store: Record<string, any> = {
aaa: '123',
bbb: null,
ccc: []
}
const getValues = <Keys extends readonly string[]>(keys: Keys): ReadonlyArray<[Keys[number], unknown]> => {
return keys.map((key) => ([key, key in store ? store[key] : null]))
}
const keyArr = ['aaa', 'bbb'] as const
getValues(keyArr) // current getValues function types: const getValues: <readonly ["aaa", "bbb"]>(keys: readonly ["aaa", "bbb"]) => readonly ["aaa" | "bbb", unknown][]
// I want: const getValues: <readonly ["aaa", "bbb"]>(keys: readonly ["aaa", "bbb"]) => readonly [["aaa", unknown], ["bbb", unknown]]
Here is the typescript Playground code link.
CodePudding user response:
You can map over the tuple using a mapped type. Mapping over a tuple type using a mapped type also produces a tuple as a result since TypeScript 3.1.
const getValues = <Keys extends readonly string[]>(keys: Keys) => {
return keys.map((key) => (
[key, key in store ? store[key] : null])
) as { [K in keyof Keys]: [Keys[K], unknown] }
}
TypeScript is not able to correctly understand that the type of the resulting array matches the return type. So a type assertion is needed.