Home > Back-end >  Typescript error 2345 when passing array as variable instead of directly
Typescript error 2345 when passing array as variable instead of directly

Time:10-23

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.

Playground

  • Related