Typescript: Typed list of keys to new Type Object

41 Views Asked by At

Have been given a typed object

type TestObj = {
    one: "up";
    two: "down";
    three: "left";
    four: "right";
}

Of which I have to choose 0 or more keys from and turn into an array

type TestObjKeys = keyof TestObj;
const chosen: TestObjKeys[] = ["one", "four"];

I need to convert this into a new typescript obj for only the keys that were chosen

type NewTestObj = Pick<TestObj, (typeof chosen)[number]>;

However the above gives me a type (equivalent to TestObj) for all keys, rather than use "one" and "four". I tried turning it into a const

const chosen2 = chosen as const;

But it errors out with

A 'const' assertions can only be applied to references to enum members, or string, number, boolean, array, or object literals.(1355)

How can I get only the chosen keys?

Sandbox

2

There are 2 best solutions below

0
T.J. Crowder On BEST ANSWER

You need to:

  1. Not put a type on chosen, so TypeScript can infer it. (You could use satisfies to make sure it satisfies a type, though, if you wanted.)
    and
  2. Use as const on the array you're assigning to chosen, so TypeScript knows it's a tuple of string literal types, not an array of string.

Like this:

const chosen = ["one", "four"] as const;
type NewTestObj = Pick<TestObj, (typeof chosen)[number]>;

Playground link

(There's also no need for the () around typeof chosen, it has higher precedence [if that's the word] than the [number] after it. Just typeof chosen[number] will do the job.)

0
Krzysztof Krzeszewski On

(typeof chosen)[number] is just TestObjKeys not chosen keys.

If you add as const assertion to chosen directly, without the explicit type it would work.

const chosen = ["one", "four"] as const;

If you still need explicit type i recommend using the satisfies operator.

const chosen = ["one", "four"] as const satisfies TestObjKeys[];