Create a type from object keys dynamically
Asked Answered
V

2

15

I have an icon-Map.json which is being created dynamically. Example:

const iconMap = {
    angleDoubleRight: 'angleDoubleRight.svg',
    angleRight: 'angleRight.svg',
    assets: 'assets.svg',
    barChart: 'barChart.svg',
    cancel: 'cancel.svg',
    chevronDown: 'chevronDown.svg',
    dotChart: 'dotChart.svg',
    dotMenu: 'dotMenu.svg',
    horizontalDots: 'horizontalDots.svg'
    ...

};
  • I can't create an interface manually from this object because I'm creating it dynamically so I can't use keyof.

  • Eventually, I want to create a type of iconMap's keys which I can use outside a component and it will strict my input to iconMap's keys only. (union or enum):

 type IconMapMember = 'angleDoubleRight' | 'angleRight' | 'assets' | ....
Vala answered 5/6, 2019 at 10:50 Comment(2)
Type is a static concept. Let's assume that you somehow defined your type like: type IconMapMember = 'angleDoubleRight' | 'angleRight'|... then what are you going to do after adding a new property to the iconMap object? Types cannot be modified in runtime, they are for compile time.Lochia
This all comes down to what you mean by "dynamically". If you mean "at runtime", then you can't do much. If you mean "programmatically in some build step that occurs before the TypeScript compiler runs", or even "in some other user-written code that the compiler can see", then you can do something about it.Abdication
A
41

In your question you say you can't use keyof, but I'm not sure why. If you have an object whose keys are known at compile time (meaning that the iconMap variable is generated before you compile TypeScript code that uses it), you can use the typeof type query operator to get its type, and then use keyof on that:

const iconMap = {
  angleDoubleRight: "angleDoubleRight.svg",
  angleRight: "angleRight.svg",
  assets: "assets.svg",
  barChart: "barChart.svg",
  cancel: "cancel.svg",
  chevronDown: "chevronDown.svg",
  dotChart: "dotChart.svg",
  dotMenu: "dotMenu.svg",
  horizontalDots: "horizontalDots.svg"
  //...
};

type IconMapMember = keyof typeof iconMap;
// type IconMapMember = "angleDoubleRight" | "angleRight" | "assets" | "barChart" 
// | "cancel" | "chevronDown" | "dotChart" | "dotMenu" | "horizontalDots" ...

Link to code

If you have some particular issue which prevents this solution from working, please update your question with more details about your build process. Hope this helps; good luck!

Abdication answered 5/6, 2019 at 16:10 Comment(3)
You are right, I was having troubles cause I got iconMap object as a JSON.. Thanks!Vala
Thanks a lot. keyof typeof constant is what I was looking for!Dramshop
I wish to do the same, but not for an object but a type instead, doesn't seem possible.Alinealinna
F
1

You can directly use Json file for create type from keys.

I wanted to use keys as type of my language files.

My '../../locales/en.json' file:

{
    "disconnect": "Disconnect",
    "connect": "Connect",
    "connecting": "Connecting",
    "connected": "Connected",
    "my_devices": "My Devices",
    "app_settings": "App Settings",
    "device_settings": "Device Settings",
    "okay": "Okay",
    "cancel": "Cancel",
    "delete": "Delete",
    "remove": "Remove",
    "no": "No",
    "yes": "Yes",
    "alert": "Alert",
    ...,
    "does_apply_pending_commands": "Should the pending commands be applied?"
}

My TranslateKeys.interface.ts file:

import en from '../../locales/en.json';
export type TranslateKeys = keyof typeof en;

Preview of TranslateKeys:

type TranslateKeys = "delete" | "disconnect" | "connect" | "connecting" | "connected" | "my_devices" | "app_settings" | "device_settings" | "okay" | "cancel" | "remove" | "no" | "yes" | "alert" | ... 181 more ... | "does_apply_pending_commands"
Fetter answered 31/7, 2024 at 8:52 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.