Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert type object keys into an array of strings type in typescript

Tags:

typescript

given the following input in typescript:

type InputObjectType = {
  a: string
  b: number
  c: {}
}

how can I get the following type:

type ObjectKeysArrayType = ['a', 'b', 'c']

so far I can only get as far as:

type AllPossibleKeys = (keyof InputObjectType)[]

which gives me ["a" | "b" | "c"] which is close, but not what I'm looking for in this case.

I need an array that always contains all the key strings in the given type object. The only way I know to enforce this, for example when a user adds a new key to the object that the key is also added to the array is via something like this.

like image 581
Chris Drackett Avatar asked May 01 '20 06:05

Chris Drackett


People also ask

How do you turn an object key into an array?

To convert an object to an array you use one of three methods: Object. keys() , Object. values() , and Object. entries() .

Can object keys be strings?

Object keys can only be strings, and even though a developer can use other data types to set an object key, JavaScript automatically converts keys to a string a value.

How do you give an object a key to type?

Use the keyof typeof syntax to create a type from an object's keys, e.g. type Keys = keyof typeof person . The keyof typeof syntax returns a type that represents all of the object's keys as strings.


Video Answer


2 Answers

Not sure if you're still looking for a solution here, but hopefully this helps.

If what you want is a type that requires that the variable be an array of strings only containing values equal to the keys of your object, then what you have listed should work.

type InputObjectType = {
  a: string
  b: number
  c: {}
}

type AllPossibleKeys = (keyof InputObjectType)[]

AllPossibleKeys will be a type equal to ("a"|"b"|"c")[]. This looks to be what you've asked for, but there is a caveat with how I'm guessing you want to use this.

const fieldArray1: AllPossibleKeys = ['a', 'b', 'c']; //valid
const fieldArray2: AllPossibleKeys = ['a', 'b', 'c', 'd']; //will throw a Typescript error
const fieldArray3: AllPossibleKeys = ['a', 'b']; //this is also valid though as each member is a valid value

If you instead want an array of all the keys in a type, there's not a way to do this explicitly that I'm aware of. However, if you are able to use an interface instead of a type, then you can do the following:

import { keys } from 'lodash';

interface InputObject = {
  a: string
  b: number
  c: {}
}

class InputObjectStub implements InputObject {
  a = null;
  b = null;
  c = null;
}

const fieldArray1 = keys(new InputObjectStub()); //returns ['a', 'b', 'c']

Note though, that this won't enforce optional attributes. If you need to do that, change your class definition to class InputObjectStub implements Required<InputObject> {...

Edit: spelling

like image 159
George Avatar answered Oct 20 '22 01:10

George


That's not currently possible because the type information is not available during runtime. You can try your code on Typescript Playground. When you do that, you'll find out that this code:

type InputObjectType = {
  a: string
  b: number
  c: {}
}

is transpiled to nothing. It simply doesn't exist after the code is transpiled to javascript. As it doesn't exist during runtime, no runtime action is possible, like iterate through its properties, or even print them out.

like image 31
julianobrasil Avatar answered Oct 20 '22 01:10

julianobrasil