1

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.
};
1
  • Does this work for you? Commented Jul 2, 2019 at 0:33

2 Answers 2

1

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.
});
Sign up to request clarification or add additional context in comments.

1 Comment

Once could use generic type inference to get a similar result; not sure if that's what OP wants though.
0

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

3 Comments

This does not enforce symbolOption to be a member of the options array. In addition to that, I don't want to create a hard-coded array type.
Is it really impossible? Because in TS objects, I can do a similar thing with generics and keyof T... Anyways. PS: The downvote isn't mine.
All good, haven't had my coffee yet. keyof T is different though isn't it? T would be defined at compile time? I'd be very surprised if it is possible

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.