简体   繁体   中英

What is the TypeScript equivalent of "PropTypes.oneOf" (restrict a variable to subset of values)

In React I can restrict a variable to subset of values, like

PropTypes.oneOf(['Home', 'About']),

How do I do that in TypeScript?

PS: I am not using TypeScript with React.

You can combine static strings (or any regular type) by defining a union type :

type SomeType = 'Home' | 'About';

Or within an interface:

interface SomeType {
  prop : 'Home' | 'About';
}

And of course you can combine other types as well:

type SomeType = string | boolean;

You can use enum .

Enums allow us to define a set of named constants. Using enums can make it easier to document intent, or create a set of distinct cases.

enum vs union-type

  • Union types are a compile time concept
  • Enums are real objects that exist at runtime
  • You can iterate over an enum
  • ... see this question

Example with enums:

enum PostStatus {
    DRAFT = "DRAFT",
    READY = "READY",
    PUBLISHED = "PUBLISHED",
}


class Post {
    constructor(private status: PostStatus) {
        this.status = status;
    }
}

const myPost = new Post(PostStatus.DRAFT);

console.log(myPost);

function doStuff(postStatus: PostStatus) {
    switch (postStatus) {
        case PostStatus.DRAFT: 
            console.log('Still working on it');
            break;
        case PostStatus.PUBLISHED:
            console.log('Done.');
        break;
        default:
            console.log('Other ...');
    }
}

Example with union type:

type PostStatus = "DRAFT" | "READY" | "PUBLISHED";


class Post {
    constructor(private status: PostStatus) {
        this.status = status;
    }

}

const myPost = new Post("DRAFT");
console.log(myPost);

function doStuff(postStatus: PostStatus) {
    switch (postStatus) {
        case "DRAFT": 
            console.log('Still working on it');
            break;
        case "PUBLISHED": 
            console.log('Done.');
            break;
        default:
            console.log('Other ...');
    }
}

Only one type among several one is a union type, and in your case a union of string literal .

You can convert an array of string literals into a union of string literals as follow:

If you do have a const array or string you can define a type :

const menuList = ["Home", "About"] as const;
type menuName = typeof menuList[number] // "Home" | "About"

If you do already have a type with the array just do:

type menuList = ["Home", "About"];
type menuItem = menuList[number] // "Home" | "About"

Here is a solution using an enum type, react proptypes and typescript props

export enum AppPage {
  Home = 'Home',
  About = 'About',
}
export MyComponentProps = {
  page: AppPage
}
export MyComponentPropTypes = {
  page: PropTypes.oneOf<AppPage>(Object.values(AppPage)).isRequired
}

export MyComponent = (props:MyComponentProps) => {
  return <div></div>
}

MyComponent.propTypes = MyComponentPropTypes

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM