Home > OS >  TypeScript: Constant array as type definition
TypeScript: Constant array as type definition

Time:06-22

I am working on a typescript project and struggle a bit with defining a fitting type. Context:

I got the following constant inside my project:

export const PROPERTYOPTIONS = [
  { value: "tag", label: "Tag" }, 
  { value: "composition", label: "Composition" },
  { value: "solvent", label: "Solvent" },
  { value: "allergen", label: "Allergen" },
  { value: "category", label: "Category" },
  { value: "other", label: "Other" },
];

Now I want to define an interface:

interface CreatePropertyModalState {
  type: { value: string; label: string };
}

How can I define that the type of the type field is a member of PROPERTYOPTIONS?

I want to dodge a type definition like:

type: { value: "tag" | "composition" | .....

CodePudding user response:

If you're not planning to change the contents of PROPERTYOPTIONS at runtime, you can mark it as immutable (as const) and define a type alias for it using typeof:

export const PROPERTYOPTIONS = [
  { value: 'tag', label: 'Tag' }, 
  { value: 'composition', label: 'Composition' },
  { value: 'solvent', label: 'Solvent' },
  { value: 'allergen', label: 'Allergen' },
  { value: 'category', label: 'Category' },
  { value: 'other', label: 'Other' },
] as const

type PropertyOptions = typeof PROPERTYOPTIONS
type PropertyOption = PropertyOption[number]
interface CreatePropertyModalState {
  // if the type should be exactly one of the options
  type: PropertyOption,
  // if you want to combine an allowed value with an arbitrary label
  type: { value: PropertyOption['value'], label: string },
}

CodePudding user response:

You can use a generic identity function to constrain the type of the array, and then typeof with an indexed access type to extract the type you want.

function checkArray<T extends string>(arr: {value: T, label: string}[]) {
    return arr;
}

export const PROPERTY_OPTIONS = checkArray([
  { value: "tag", label: "Tag" }, 
  { value: "composition", label: "Composition" },
  { value: "solvent", label: "Solvent" },
  { value: "allergen", label: "Allergen" },
  { value: "category", label: "Category" },
  { value: "other", label: "Other" },
]);

type PropertyOption = typeof PROPERTY_OPTIONS[number]
// type PropertyOption = {
//     value: "tag" | "composition" | "solvent" | "allergen" | "category" | "other";
//     label: string;
// }

interface CreatePropertyModalState {
    type: PropertyOption
}

Playground Link

  • Related