简体   繁体   中英

Better way to declare string enums and use them - Typescript

 enum ROUTES {
  REQUEST_OTP = 'REQUEST_OTP',
  LOGIN = 'LOGIN',
}

export const urls: { [key: string]: string } = {
  [ROUTES.REQUEST_OTP]: '/v1/auth/otp',
  [ROUTES.LOGIN]: '/v1/auth/login',
};

export function getUrl(route: string) {
  return BASE_URL + urls[route];
}

Is there a better way to write ROUTES enum rather than repeatedly writing string literals next to it?

There seems to be a repetition of code in the my code writing the string enums.

Trying out mapped types:

 type ROUTE_KEY = 'REQUEST_OTP' | 'LOGIN';

export const urls: { [key: string]: string } = {
  REQUEST_OTP: '/v1/auth/request-otp',
  LOGIN: '/v1/auth/login/?version=v2',
};

export function getUrl(route: ROUTE_KEY) {
  return BASE_URL + urls[route];
}

The key to avoiding redundancy in this situation is to compute your types from your values while leveraging type inference. Every JavaScript expression has a corresponding TypeSript type. As Bergi metioned, we can obtain the type from a value by using the typeof operator in type position. Together with the keyof type operator we use this to compute a union type consisiting of all property keys in urls .

export const urls = {
  EQUEST_OTP: '/v1/auth/request-otp',
  LOGIN: '/v1/auth/login/?version=v2'
};

export type RouteKey = keyof typeof urls;

export function getUrl(route: RouteKey) {
  return BASE_URL + urls[route];
}

Playground Link

In the above, we used typeof type operator to obtain the type of the value urls , which is

{
  REQUEST_OTP: string,
  LOGIN: string
}

We then used the keyof type operator to compute a union type consisting of the property keys of the that type, which is

'REQUEST_OTP' | 'LOGIN'

Notice how the variable urls has no type annotation. The use of type inference not only increases brevity but also results in a far stronger type than { [key: string]: string } .

Alternately, we can actually could do without declaring the type alias RouteKey and just write

export function getUrl(route: keyof typeof urls) {
  return BASE_URL + urls[route];
}

It's not clear if this is better, because you're not specific about what is bad with your current sample. However, this is how I would write this:


type RouteKey = 'request-otp' | 'login';


export const urls: { [key: RouteKey]: string } = {
  'request-otp': '/v1/auth/otp',
  'login:': '/v1/auth/login',
};


export function getUrl(route: RouteKey) {
  return BASE_URL + urls[route];
}

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