如何正确键入枚举条目数组?
How to properly type an array of enum entries?
我有一个基本的enum
如下:
export enum Fruit {
apple,
banana
}
我想导出 enum
keys
的固定 Array
export const Fruits = Object.entries(Fruit).map(f => f[0]);
应该根据需要给出 ['apple', 'banana']
和 Fruits
typed as string[]
.
为了尝试更具体的 键入 ,我添加了 as keyof typeof Fruit
这样的
export const Fruits = Object.entries(Fruit).map(f => f[0] as keyof typeof Fruit);
这给了我类型 const Fruits: ("apple" | "banana")[]
。 这是我能得到的最多吗?
我的目标是获得像 const Fruits: ["apple", "banana"] = ....
这样的 typing,我认为这是我应该制作的完美 typing。
脚注:
我不想使用其他定义 enum
的方法,只是为了避免冗余,
export enum Fruit {
apple = 'apple',
banana = 'banana'
}
我很乐意做这样的事情:
interface Meal {
fruit: keyof tpeof Fruit // since the default enum values are integers, use keys
}
所以我很乐意有一个不需要我这样做的解决方案。如果没有其他办法,请在您的回答中提及。
请记住,不能保证 Object.entries
或 Object.keys
保留键的顺序。因此,您需要 return 所有可能状态的排列,而不仅仅是 ['apple', 'banana']
.
在这种情况下,它应该是 ['apple', 'banana'] | ['banana', 'apple']
。
export enum Fruit {
apple,
banana
}
// credits goes to https://twitter.com/WrocTypeScript/status/1306296710407352321
type TupleUnion<U extends PropertyKey, R extends any[] = []> = {
[S in U]: Exclude<U, S> extends never ? [...R, S] : TupleUnion<Exclude<U, S>, [...R, S]>;
}[U];
const keys = <
Keys extends string,
Obj extends Record<Keys, unknown>
>(obj: Obj) =>
Object.keys(Fruit) as TupleUnion<keyof Obj>;
const result = keys(Fruit)
// ["apple", "banana"] | ["banana", "apple"]
type Check = typeof result
Playground
我使用 keys
而不是 entries
因为我们只对键感兴趣。
Here, in my blog, you can find more about convertiong union to tuples and function arguments inference
那么,哪个枚举更好:值是整数还是字符串?
首先,枚举有其自身的缺陷。
考虑这个例子:
export enum Fruit {
apple,
banana
}
const fruit = (enm: Fruit) => {}
fruit(100) // ok, no error
安全吗 - 不!
如果您有位掩码,则必须使用带整数的枚举。
最好使用带有字符串值的枚举:
export enum Fruit {
apple = 'apple',
banana = 'banana'
}
如果您仍想对整数使用枚举,请考虑以下示例:
const enum Fruit {
apple,
banana,
}
const fruit = (enm: typeof Fruit) => { }
fruit(100) // expected error
Object.keys(Fruit) // impossible
如果您想将枚举与整数一起使用,并且 Object.keys/entries
您可能希望使用 最安全的 方法:
export const Fruit = {
apple: 0,
banana: 1,
} as const
const fruit = (enm: typeof Fruit) => { }
fruit(100) // expected safe
我有一个基本的enum
如下:
export enum Fruit {
apple,
banana
}
我想导出 enum
keys
Array
export const Fruits = Object.entries(Fruit).map(f => f[0]);
应该根据需要给出 ['apple', 'banana']
和 Fruits
typed as string[]
.
为了尝试更具体的 键入 ,我添加了 as keyof typeof Fruit
这样的
export const Fruits = Object.entries(Fruit).map(f => f[0] as keyof typeof Fruit);
这给了我类型 const Fruits: ("apple" | "banana")[]
。 这是我能得到的最多吗?
我的目标是获得像 const Fruits: ["apple", "banana"] = ....
这样的 typing,我认为这是我应该制作的完美 typing。
脚注:
我不想使用其他定义 enum
的方法,只是为了避免冗余,
export enum Fruit {
apple = 'apple',
banana = 'banana'
}
我很乐意做这样的事情:
interface Meal {
fruit: keyof tpeof Fruit // since the default enum values are integers, use keys
}
所以我很乐意有一个不需要我这样做的解决方案。如果没有其他办法,请在您的回答中提及。
请记住,不能保证 Object.entries
或 Object.keys
保留键的顺序。因此,您需要 return 所有可能状态的排列,而不仅仅是 ['apple', 'banana']
.
在这种情况下,它应该是 ['apple', 'banana'] | ['banana', 'apple']
。
export enum Fruit {
apple,
banana
}
// credits goes to https://twitter.com/WrocTypeScript/status/1306296710407352321
type TupleUnion<U extends PropertyKey, R extends any[] = []> = {
[S in U]: Exclude<U, S> extends never ? [...R, S] : TupleUnion<Exclude<U, S>, [...R, S]>;
}[U];
const keys = <
Keys extends string,
Obj extends Record<Keys, unknown>
>(obj: Obj) =>
Object.keys(Fruit) as TupleUnion<keyof Obj>;
const result = keys(Fruit)
// ["apple", "banana"] | ["banana", "apple"]
type Check = typeof result
Playground
我使用 keys
而不是 entries
因为我们只对键感兴趣。
Here, in my blog, you can find more about convertiong union to tuples and function arguments inference
那么,哪个枚举更好:值是整数还是字符串?
首先,枚举有其自身的缺陷。 考虑这个例子:
export enum Fruit {
apple,
banana
}
const fruit = (enm: Fruit) => {}
fruit(100) // ok, no error
安全吗 - 不!
如果您有位掩码,则必须使用带整数的枚举。
最好使用带有字符串值的枚举:
export enum Fruit {
apple = 'apple',
banana = 'banana'
}
如果您仍想对整数使用枚举,请考虑以下示例:
const enum Fruit {
apple,
banana,
}
const fruit = (enm: typeof Fruit) => { }
fruit(100) // expected error
Object.keys(Fruit) // impossible
如果您想将枚举与整数一起使用,并且 Object.keys/entries
您可能希望使用 最安全的 方法:
export const Fruit = {
apple: 0,
banana: 1,
} as const
const fruit = (enm: typeof Fruit) => { }
fruit(100) // expected safe