Question was already asked here but both the solutions provided don't address nor solve the issue
I was following some TypeScripts examples about generics, in the specific this one.
The example is pretty straightforward:
function pickObjectKeys<T, K extends keyof T>(obj: T, keys: K[]) {
let result = {} as Pick<T, K>
for (const key of keys) {
if (key in obj) {
result[key] = obj[key]
}
}
return result
}
const language = {
name: "TypeScript",
age: 8,
extensions: ['ts', 'tsx']
}
const ageAndExtensions = pickObjectKeys(language, ['age', 'extensions'])
This works. However, if passing the array as a variable, like so:
const keys = ['age', 'extensions']
...
pickObjectKeys(language, keys)
the TypeScript compiler gives error 2345:
Argument of type 'string[]' is not assignable to parameter of type '("age" | "extensions" | "name")[]'.
Type 'string' is not assignable to type '"age" | "extensions" | "name"'.
What's the catch? How to address this issue?
CodePudding user response:
First, consider making keys
readonly:
function pickObjectKeys<T, K extends keyof T>(obj: T, keys: readonly K[]) {
this will allow you to pass readonly arrays now (previously it would've errored).
The easiest way to get around this is to use a const assertion:
const keys = ['age', 'extensions'] as const; // readonly ["age", "extensions"]
pickObjectKeys(language, keys); // OK
but you could also cast to ["age", "extensions"]
or ("age" | "extensions")[]
. However, that does mean you would repeat yourself, so I suggest staying with as const
.