作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
给定一些 enum MyEnum {ONE, TWO}
,我想写一个函数叫做like
useMyFun(MyEnum, MyEnum.ONE);
type StringKeyOf<T> = Extract<keyof T, string>;
type EnumNumber<E> = Record<StringKeyOf<E>, number>;
function useMyFun<E extends EnumNumber<E>, V extends number=number> (
anEnum: E,
initialState: number) : {value: V, setValue: (v: V) => void}
{
const [value, setValue] = useState<V>(initialState as V);
//.... more stuff using both arguments omitted
return {value, setValue};
}
function useState<V>(initialState: V) {
const result: [V, (v: V) => void] = [initialState, v => { }];
return result;
}
useMyFun(MyEnum, -1)
同样,这是错误的。请注意,我只关心上面的枚举,即具有默认数值、没有指定值和没有
const
的枚举修饰符。
value: MyEnum
而不是
number
.
MyEnum
的运行时值是
{0: 'ONE', 1: 'TWO', ONE: '0', TWO: '1'}
这意味着上面的输入实际上是错误的。然而,这是编译第一个参数的唯一方法。处理
MyEnum
时的第二个参数实际上应该是
0 | 1
,但我无法让它工作。
最佳答案
相关问题可以找here
还有另一种方法可以确定初始值是否有效。
如您所知,TS 可能会处理 enum
作为 number
或作为对象或typeof enum
. typescript 以类似的方式处理 classes
.
我们需要一些如何获取enum
的数字键.
让我们尝试遍历 enum
键:
enum MyEnum {
ONE,
TWO
}
type Enumerate<Enum extends number | string> = keyof {
[Prop in Enum]: Prop
}
// non generic version
type Keys = keyof typeof MyEnum
type Enumerate2 = keyof {
[Prop in Keys]: Prop
}
type Result = Enumerate<MyEnum> // MyEnum, not good
它不起作用,因为 TS 足够聪明,可以找出我们正在迭代枚举键。因此我们得到
MyEnum
而不是
0 | 1
.
Prop
键入字符串以欺骗 typescript 。
enum MyEnum {
ONE,
TWO
}
type Enumerate<Enum extends number | string> = keyof {
[Prop in `${Enum}`]: Prop
}
type Result = Enumerate<MyEnum> // "0" | "1"
现在好多了。但这仍然不是我们想要的。在当前版本的 typescript 中,无法以通用方式从字符串中提取数字。
"0" extends
${数字} ? ...`
enum MyEnum {
ONE,
TWO
}
type Enumerate<Enum extends number | string> = keyof {
[Prop in `${Enum}`]: Prop
}
type Result = Enumerate<MyEnum> // "0" | "1"
type Values<T> = T[keyof T]
type IsKeyValid<InitialValue extends number, Enum extends Record<string | number, string | number>> =
`${InitialValue}` extends Enumerate<Values<Enum>> ? InitialValue : never
function useMyFun<
Enum extends Record<string | number, string | number>,
InitialValue extends number,
>(anEnum: Enum, initialState: IsKeyValid<InitialValue, Enum>) { }
useMyFun(MyEnum, MyEnum.ONE) // ok
useMyFun(MyEnum, 0) // ok
useMyFun(MyEnum, -1) // error
useMyFun(MyEnum, NaN) // error
Playground
Enum
- 是枚举的推断类型
InitialValue
- 是第二个参数的推断类型。
IsKeyValid
- 是一种实用程序类型,用于检查是否包装成字符串
InitialValue
是否等于允许的枚举键。如果相等 - 返回
InitialValue
, 否则返回
never
附言相关
question使用 React 组件 Prop
关于typescript - 如何键入带枚举的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62268023/
我是一名优秀的程序员,十分优秀!