Luiz Felipe
Luiz Felipe

Reputation: 997

Enforce string type to be part of array of string in TypeScript

Let's say I have the following interface:

interface Option {
  options: string[];
  symbolOption: string;
}

How can I enforce that the symbolOption must be included in the options array?

Example of what I need

This will be OK:

const option: Option = {
  options: ['a', 'b'],
  symbolOption: 'a' // ✅ OK
};

But this will not be OK:

const option: Option = {
  options: ['a', 'b'],
  symbolOption: 'c' // 🔴 `c` is not included in the `options` list.
};

Upvotes: 1

Views: 64

Answers (2)

Shaun Luttin
Shaun Luttin

Reputation: 141512

This works (playground) though I am not sure whether providing the generic arguments of 'a' | 'b' will suit your requirement or not.

interface Option<T> {
    options: T[];
    symbolOption: T;
}

// This will be OK:
const optionGood: Option<'a' | 'b'> = {
    options: ['a', 'b'],
    symbolOption: 'a' // ✅ OK
};

// But this will not be OK:
const optionBad: Option<'a' | 'b'> = {
    options: ['a', 'b'],
    symbolOption: 'c' // 🔴 `c` is not included in the `options` list.
};

Here is another alternative courtesy of jcalz (playground).

interface OptionConstraint<
  T extends string,
  O extends OptionConstraint<T, O>
> {
  options: T[];
  symbolOption: O["options"][number];
}

const asOption = <T extends string, O extends OptionConstraint<T, O>>(o: O) =>
  o;

// This will be OK:
const optionGood = asOption({
  options: ["a", "b"],
  symbolOption: "a" // ✅ OK
});

// But this will not be OK:
const optionBad = asOption({
  options: ["a", "b"],
  symbolOption: "c" // 🔴 `c` is not included in the `options` list.
});

Upvotes: 1

Chris
Chris

Reputation: 58182

If I understand what you are asking, it would be as simple as:

interface Option {
  options: Array<'a'|'b'>;
  symbolOption: string;
}

Edit Edit based on comments.

What you are asking isn't possible, TypeScript is largely a compile type check, you can't have a dynamic type value to represent an interface type.

Have a read of How to check the object type on runtime in TypeScript? to understnad what can and can't be done at runtime

Upvotes: 0

Related Questions