0

I am trying to use TypeScript to describe the interface for an object. Faced such a problem: How to set an opportunity with help of an interface, limited values ​​in an array. Example:

export interface IChannel {
  title: string
  name: string,
  signal: ["discrete", "analog", "text"] | ["discrete", "analog"] | ["discrete"] | ["analog"] | ["text"] | ["analog", "text"], // OMG... IT"S BAD !!!
  enabled: boolean
  "description": string,
  "isChangeVisibility": boolean
}

Need filed signal = ["discrete" OR/AND "analog" OR/AND "text"] This field must contain only these values. Array length (may be 1, 2 or 3 elements) Thanks for any help. I will sit experimenting.

2 Answers 2

3

Using an enum like @axiac suggested is one solution, but then if you want to create an object of type IChannel you have to use the enum values (e.g. you can't do signal: ['discrete'], it has to be signal: [SignalType.discrete] or signal: ['discrete'] as SignalType[]).

IMO an union of literal types is simpler and does not produce any additional JavaScript output (enums are compiled to objects):

type SignalType = 'discrete' | 'analog' | 'text';

export interface IChannel {
  title: string;
  name: string;
  signal: SignalType[];
  enabled: boolean;
  description: string;
  isChangeVisibility: boolean;
}

The downside is that something like ['discrete', 'discrete'] will be okay for the compiler. If it's important to enforce uniqueness of values then your current solution is the only reasonable one I think.

You could also do signal: [SignalType, SignalType?, SignalType?], which enforces the number of elements to 1, 2 or 3 (but still doesn't solve the issue with value uniqueness).

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you @paolostyle. This works well. At the expense of uniqueness is not critical. It is ideal for a compiler.
1

An enum is the best type for the values that can be used in the field signal:

enum SignalType {
  discrete = 'discrete',
  analog = 'analog',
  text = 'text',
}

export interface IChannel {
  title: string
  name: string,
  signal: SignalType[]
  enabled: boolean
  description: string,
  isChangeVisibility: boolean
}

3 Comments

But this does not constraint the possibility of duplicate keys (?..
@VRoxa it doesn't, but there's no good way to achieve it any other way than what OP already has, stackoverflow.com/a/57021889/1708094 could help but IMO it's not worth the effort
Another option is to make signal a numeric field and use numeric values combined with the bitwise OR operator. This has advantages (the duplicate values in its definition do not matter) and disadvantages (the type accepts invalid values, the operations are a bit more cryptic for newbies).

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.