Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to get string literal types from Record defined as const

I am able to infer types when I’m not using Record

export const TabsDefinition = {
dimensionDetails: [
  { name: 'general', label: 'General' },
  { name: 'settings', label: 'Settings' },
  { name: 'list', label: 'List' },
],
} as const;

type MyNames = typeof TabsDefinition.dimensionDetails[number]['name'];

With this approach MyNames is infered as "general" | "settings" | "list"

But I want to use type for array of items – so I created this

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

type Tab = {
  name: string;
  label: string;
};

export const TabsDefinition: Record<string, ReadonlyArray<Tab>> = {
  dimensionDetails: [
    { name: 'general', label: 'General' },
    { name: 'settings', label: 'Settings' },
    { name: 'list', label: 'List' },
  ],
} as const;

type MyNames = typeof TabsDefinition.dimensionDetails[number]['name'];

but then MyNames type is infered as string

>Solution :

When you assign a const object literal to a variable of type Record<string, ReadonlyArray<Tab>> the information is lost – now the compiler assumes that TabsDefinition is can contain any value conforming to that type.

The solution is to keep the precise type of your object literal, but force TS to type check against Record<string, ReadonlyArray<Tab>>.

There is an open issue "satisfies" operator to ensure an expression matches some type designed precisely to address that need.

Until it lands in an official release, you can use a constrained identity function:

type Tab = {
  name: string;
  label: string;
};

function createTabsDefinition <T extends Record<string, ReadonlyArray<Tab>>>(def: T): T {
  return def;
}

export const TabsDefinition = createTabsDefinition({
  dimensionDetails: [
    { name: 'general', label: 'General' },
    { name: 'settings', label: 'Settings' },
    { name: 'list', label: 'List' },  
  ],
} as const);

type MyNames = typeof TabsDefinition.dimensionDetails[number]['name'];

Playground link

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading