javascript - Typescript type for an array that can contain only elements from a specific list - Stack Overflow

I want to declare a type for an array that can contain maximum one of the following strings: 'firs

I want to declare a type for an array that can contain maximum one of the following strings: 'first', 'second', 'third'.

Some valid examples of how that array could be:

  • []
  • [ 'first' ]
  • [ 'first', 'second' ]
  • [ 'first', 'second', 'third' ]
  • [ 'first', 'third' ]
  • [ 'second', 'third' ]

Some invalid arrays:

  • [ 'other-value' ] // no other values should be accepted
  • [ 'first', 'first' ] // no duplicates accepted

The types I've wrote:

export enum MyOptions {
  first = 'first',
  second = 'second',
  third = 'third'
}

export type MyType = {
  name: string;
  email: string;
  listings: {
   MyOptions;
  }[];
};

It has a warning saying Member 'MyOptions' implicitly has an 'any' type, but a better type may be inferred from usage.

So if it is changed to:

export type MyType = {
  name: string;
  email: string;
  listings: {
   options: MyOptions;
  }[];
};

Now, there is no warning but it has that extra options value that I don't think it must be added.

Any ways to fix this?

I want to declare a type for an array that can contain maximum one of the following strings: 'first', 'second', 'third'.

Some valid examples of how that array could be:

  • []
  • [ 'first' ]
  • [ 'first', 'second' ]
  • [ 'first', 'second', 'third' ]
  • [ 'first', 'third' ]
  • [ 'second', 'third' ]

Some invalid arrays:

  • [ 'other-value' ] // no other values should be accepted
  • [ 'first', 'first' ] // no duplicates accepted

The types I've wrote:

export enum MyOptions {
  first = 'first',
  second = 'second',
  third = 'third'
}

export type MyType = {
  name: string;
  email: string;
  listings: {
   MyOptions;
  }[];
};

It has a warning saying Member 'MyOptions' implicitly has an 'any' type, but a better type may be inferred from usage.

So if it is changed to:

export type MyType = {
  name: string;
  email: string;
  listings: {
   options: MyOptions;
  }[];
};

Now, there is no warning but it has that extra options value that I don't think it must be added.

Any ways to fix this?

Share Improve this question edited Aug 15, 2022 at 12:06 Leo Messi asked Aug 15, 2022 at 10:09 Leo MessiLeo Messi 6,23622 gold badges80 silver badges155 bronze badges
Add a ment  | 

4 Answers 4

Reset to default 6

You can use the Set data structure.

export type Options = 'first' | 'second' | 'third'
export type Listing = Set<Options>

export type MyType = {
    name: string;
    email: string;
    listings: Listing;
};

const myType = {
  name: 'name',
  email: 'email',
  listing: new Set(['first', 'second'])
}

Then you will be sure that there are no repeated options in your listing. Note: actually you can pass repeated options but Set will ignore them.

I think you have an extra set of braces that you don't need.

export type MyType = {
  name: string;
  email: string;
  listings: {
   MyOptions;
  }[];
};

should be changed to

export type MyType = {
  name: string;
  email: string;
  listings: MyOptions[];
};

You also have a more concise option: use string literal types:

export type MyType = {
  name: string;
  email: string;
  listings: ('first' | 'second' | 'third')[];
};

It should be like this:

export type MyType = {
    name: string;
    email: string;
    listings: MyOptions[];
};

Let's assume you have variable named x of MyType, then to push new value to listings member you can do x.listings.push(MyOptions.first)

The second solution just means that you now have an object that could look like:

const exampleObject = {
  name: 'Ralf';
  email: '[email protected]';
  listings: {
   options: 'first';
  }[];
};

Which is not what you intend, because you can´t have a ['first', 'second'] there, but only ONE value.

If you use the style

listings: MyOptions[];

Then it allows also the content ['first', 'first'].

As far as i know, there is no way to limit the possible values not only by its content, but also by its amount (having at maximum one of each values) via typescript types.

So you would have to create your own logic.

For example having a small business object

class Options {
  private _values: MyOptions[] = [];

  addOption(option:MyOption){
    if(this._values.some(option)){
      return; // or throw an error, depends on your usecase
    }
    this.values.concat(option);
  }

  get options():MyOptions{
    return this._values;
  }
}

Now you can have your wrapper type:

export type MyType = {
  name: string;
  email: string;
  listings: Options
};

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744228850a4564143.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信