简体   繁体   English

字符串文字类型,在Typescript中包含变量

[英]String Literal Types with variables in Typescript

my codes: 我的代码:

export const LOAD_USERS = 'LOAD_USERS';
export const CREATE_USER = 'CREATE_USER';
export interface ACTION {
  type: string,
  payload: any
}

I want to restrict the ACTION.type to be either 'LOAD_USERS' or 'CREATE_USERS'. 我想将ACTION.type限制为'LOAD_USERS'或'CREATE_USERS'。 I can do this by String Literal type: 'LOAD_USERS'|'CREATE_USERS' . 我可以通过String Literal type: 'LOAD_USERS'|'CREATE_USERS'执行此操作type: 'LOAD_USERS'|'CREATE_USERS' But can not do it with variables type: LOAD_USERS | CREATE_USERS 但是不能用变量type: LOAD_USERS | CREATE_USERS type: LOAD_USERS | CREATE_USERS . type: LOAD_USERS | CREATE_USERS My editor prompts "can not find name 'LOAD_USERS'". 我的编辑器提示“找不到名字'LOAD_USERS'”。 Is there a way to use variables to do this? 有没有办法使用变量来做到这一点? There could be typo when typing the same string in more than one place. 在多个地方输入相同的字符串时可能会出现拼写错误。

If you want to ensure that the string in your variables will be the action type, then you should use a type alias and explicitly type the variables with that type: 如果要确保变量中的字符串是操作类型,则应使用类型别名并使用该类型显式键入变量:

export type ActionNames = 'LOAD_USERS' | 'CREATE_USER';
export const LOAD_USERS: ActionNames = 'LOAD_USERS';
export const CREATE_USER: ActionNames = 'CREATE_USER';

export interface ACTION {
  type: ActionNames;
  payload: any;
}

If the strings in the variables don't match one of the strings in ActionTypes , then you'll get an error, which is desired to prevent mistakes. 如果变量中的字符串与ActionTypes中的某个字符串不匹配,那么您将收到一个错误,这是为了防止错误。 For example, this would error: 例如,这会出错:

export type ActionNames = 'LOAD_USERS' | 'CREATE_USER';
export const LOAD_USERS: ActionNames = 'LOAD_USERS_TYPO'; // error, good

Update 更新

Note that in newer versions of TypeScript the following is another option: 请注意,在较新版本的TypeScript中,以下是另一种选择:

const actionNames = ['LOAD_USERS', 'CREATE_USER'] as const;
type ActionNames = typeof actionNames[number]; // typed as 'LOAD_USERS' | 'CREATE_USER'

Also, looking back on this question, you probably want to declare your actions with a common string literal type property that's differentiated by the string literal type (see discriminated unions ). 另外,回顾这个​​问题,您可能希望使用由字符串文字类型区分的公共字符串文字类型属性来声明您的操作(请参阅区分的联合 )。

For example: 例如:

interface LoadUsersAction {
    type: "LOAD_USERS";
}

interface CreateUserAction {
    type: "CREATE_USER";
    name: string;
    // etc...
}

type Actions = LoadUsersAction | CreateUserAction;

Also, I recommend not bothering with the variables. 另外,我建议不要打扰变量。 Using the strings directly is type safe. 直接使用字符串是类型安全的。

You can use the typeof operator, it returns the inferred type: 您可以使用typeof运算符,它返回推断类型:

export const LOAD_USERS = 'LOAD_USERS';
export const CREATE_USER = 'CREATE_USER';
export interface ACTION {
  type: typeof LOAD_USERS | typeof CREATE_USER,
  payload: any
}

Since TypeScript 2.4 you can use enums with string members. 从TypeScript 2.4开始,您可以使用带有字符串成员的枚举。 Enums define a set of named constants. 枚举定义了一组命名常量。

export enum UserActions{
    LOAD_USERS = "LOAD_USERS",
    CREATE_USER = "CREATE_USER"
}

export interface ACTION {
    type: UserActions,
    payload: any
}

You cannot totally eliminate the duplication, but you can reduce it to the bare minimum: 你不能完全消除重复,但你可以将它减少到最低限度:

type nameIt = 'LOAD_USERS' | 'CREATE_USERS'
export const LOAD_USERS = 'LOAD_USERS';
export const CREATE_USER = 'CREATE_USER';

This allows you to use the nameIt type elsewhere, but it does mean repeating the strings in your constants and in the type. 这允许您在其他地方使用nameIt类型,但它确实意味着重复常量和类型中的字符串。

Alternatively, if you are writing a new piece of code, you might prefer to use an enum . 或者,如果您正在编写新代码,则可能更喜欢使用enum

Simplifying the existing answers further, 进一步简化现有答案,

export type ActionTypes = 'LOAD_USERS' | 'CREATE_USER';

is sufficient by itself. 本身就足够了。 To refer to a specific action type, just use the quoted string literal: 要引用特定的操作类型,只需使用带引号的字符串文字:

'LOAD_USERS'

In some other languages we avoid repeating such string literals and prefer to name them with a declaration. 在其他一些语言中,我们避免重复这样的字符串文字,而更喜欢用声明来命名它们。 But that's because those other languages don't have string literal types! 但那是因为那些其他语言没有字符串文字类型! In TypeScript, 'LOAD_USERS' already is a compile-time name for a statically-checkable type. 在TypeScript中, 'LOAD_USERS'已经静态可检查类型的编译时名称。 You don't necessarily need to give it another name. 你不一定要给它另一个名字。

Example: 例:

declare function doAction(action: ActionTypes);

doAction('LOAD_USERS'); // okay

doAction('LOAD_USES'); // error: typo is caught by compiler

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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