打字稿强制该字符串值是对象值之一
Typescript enforce that string value is one of the object values
我有这个常量声明:
export const Actions = {
VIEW: 'view',
EDIT: 'edit',
};
现在假设我有如下函数:
// how to ensure action variable below is string of value either view or edit
function insertAction(action: string): void {
console.log('trust me i inserted the action');
}
我的目标是让动作参数只有值 view
| edit
并动态地理解这一点,所以请不要建议使用联合解决方案,因为我已经知道它不适合我的目的。
我试过像下面这样的签名
function insertAction(action: typeof Actions[keyof typeof Actions]
但它不起作用。
我仍然可以调用函数 insertAction('whatever')
并且 ts 编译不会使 linter 失败。
在我的 package.json 中,我使用带有 PHPStorm 编辑器和 nextjs 的 typescript 版本 4.4.2
"typescript": "^4.4.2"
您当前的解决方案:
function insertAction(action: typeof Actions[keyof typeof Actions])
应该可以工作,只要您使用 as const
modifier:
声明 Actions
对象
export const Actions = {
VIEW: 'view',
EDIT: 'edit',
} as const; // <-- note the assertion here.
这是有效的,因为默认情况下,当您声明一个没有显式类型的对象时,例如:
export const Actions = {
VIEW: 'view',
EDIT: 'edit',
}
TypeScript 可以看到 变量 是常量,不能重新分配。然而,由于它被分配了一个具有潜在 可变值 的对象,TypeScript 将为该对象推断类型:
{
VIEW: string;
EDIT: string;
}
您想要的值类型不是 string
,而是 "view"
和 "edit"
的确切 文字字符串类型 .使用 as const
修饰符会通知 TypeScript 对象 的值不会发生变化 ,因此它将为这些值推断出更严格的文字字符串类型。
然后,由于值类型分别是确切的字符串 "view"
和 "edit"
,使用 typeof Actions[keyof typeof Actions]
将产生联合类型 "view" | "edit"
,这正是需要的你的参数类型。
为什么不使用枚举和赋值 action:EAction
?
应该是这样的:
export enum EActions {
VIEW = 'view',
EDIT = 'edit',
}
你的函数
function insertAction(action: EAction): void {
console.log('trust me i inserted the action');
}
会告诉你输入错误:
insertAction('whatever'); // will show you error
“whatever”类型的参数不能分配给 'EAction' 类型的参数。
使用您的 EActions:
insertAction(EAction.VIEW);
我觉得读起来会更容易。
示例:
JS Playground
我有这个常量声明:
export const Actions = {
VIEW: 'view',
EDIT: 'edit',
};
现在假设我有如下函数:
// how to ensure action variable below is string of value either view or edit
function insertAction(action: string): void {
console.log('trust me i inserted the action');
}
我的目标是让动作参数只有值 view
| edit
并动态地理解这一点,所以请不要建议使用联合解决方案,因为我已经知道它不适合我的目的。
我试过像下面这样的签名
function insertAction(action: typeof Actions[keyof typeof Actions]
但它不起作用。
我仍然可以调用函数 insertAction('whatever')
并且 ts 编译不会使 linter 失败。
在我的 package.json 中,我使用带有 PHPStorm 编辑器和 nextjs 的 typescript 版本 4.4.2
"typescript": "^4.4.2"
您当前的解决方案:
function insertAction(action: typeof Actions[keyof typeof Actions])
应该可以工作,只要您使用 as const
modifier:
Actions
对象
export const Actions = {
VIEW: 'view',
EDIT: 'edit',
} as const; // <-- note the assertion here.
这是有效的,因为默认情况下,当您声明一个没有显式类型的对象时,例如:
export const Actions = {
VIEW: 'view',
EDIT: 'edit',
}
TypeScript 可以看到 变量 是常量,不能重新分配。然而,由于它被分配了一个具有潜在 可变值 的对象,TypeScript 将为该对象推断类型:
{
VIEW: string;
EDIT: string;
}
您想要的值类型不是 string
,而是 "view"
和 "edit"
的确切 文字字符串类型 .使用 as const
修饰符会通知 TypeScript 对象 的值不会发生变化 ,因此它将为这些值推断出更严格的文字字符串类型。
然后,由于值类型分别是确切的字符串 "view"
和 "edit"
,使用 typeof Actions[keyof typeof Actions]
将产生联合类型 "view" | "edit"
,这正是需要的你的参数类型。
为什么不使用枚举和赋值 action:EAction
?
应该是这样的:
export enum EActions {
VIEW = 'view',
EDIT = 'edit',
}
你的函数
function insertAction(action: EAction): void {
console.log('trust me i inserted the action');
}
会告诉你输入错误:
insertAction('whatever'); // will show you error
“whatever”类型的参数不能分配给 'EAction' 类型的参数。
使用您的 EActions:
insertAction(EAction.VIEW);
我觉得读起来会更容易。
示例: JS Playground