繁体   English   中英

反应 typescript:使用“Object.freeze”(枚举)作为类型

[英]react typescript: use "Object.freeze" (enum) as type

我有这个“枚举”:

export const AuthEnum = Object.freeze({
      AUTHENTICATED: 1,
    UNAUTHENTICATED: 2,
    PENDING: 3
})

这会起作用,但有点误导:

const [isAuthenticated, setIsAuthenticated] = useState<number>(AuthEnum.PENDING);

这是我想做的,但不起作用:

const [isAuthenticated, setIsAuthenticated] = useState<AuthEnum>(AuthEnum.PENDING);

这也不起作用:

const [isAuthenticated, setIsAuthenticated] = useState<typeof AuthEnum>(AuthEnum.PENDING);

是否有可能以某种方式表明 state 的类型是 AuthEnum?

这个useState<AuthEnum>(AuthEnum.PENDING)不起作用,因为AuthEnum是一个运行时值,它被用作一种类型。 仅当AuthEnum是枚举时才允许以这种方式使用它。

这个const [isAuthenticated, setIsAuthenticated] = useState<typeof AuthEnum>(AuthEnum.PENDING); 不起作用,因为typeof AuthEnum是 object 并且您传递的是数字AuthEnum.PENDING

事实上,您只想使用AuthEnum的值。 为了做到这一点,首先你应该使用as const断言来缩小 object 值的类型。

import React, { useState } from 'react'

const FakeEnum = {
    AUTHENTICATED: 1,
    UNAUTHENTICATED: 2,
    PENDING: 3
} as const // immutability assertion

export const AuthEnum = Object.freeze(FakeEnum)

type Values<T> = T[keyof T]

const App = () => {
    const [isAuthenticated, setIsAuthenticated] = useState<Values<typeof AuthEnum>>(AuthEnum.PENDING);

    setIsAuthenticated(1) // ok
    setIsAuthenticated(2) // ok
    setIsAuthenticated(3) // ok
    setIsAuthenticated(4) // expected error

    return null
}

操场

Values实用程序类型返回所有 object 值的联合。


有“as const”的原因是什么?

没有as const AuthEnum就变成了:

Readonly<{
    AUTHENTICATED: number;
    UNAUTHENTICATED: number;
    PENDING: number;
}>

而使用as const - 所有 object 值都严格缩小:

Readonly<{
    readonly AUTHENTICATED: 1;
    readonly UNAUTHENTICATED: 2;
    readonly PENDING: 3;
}>

as const使您的 object 不仅不可变,而且还缩小了所有值类型。

这就是为什么问题的作者使用 immutable object 而不是enum的原因。 既然您只有 3 个属性: 1, 2, 3为什么您允许将setIsAuthenticated function 与任何其他 arguments 一起调用? 很明显,调用setIsAuthenticated(1000)是无效的,应该突出显示为错误。

请使用常规enum查看此示例:

enum AuthEnum {
    AUTHENTICATED = 1,
    UNAUTHENTICATED = 2,
    PENDING = 3
}

const App = () => {
    const [isAuthenticated, setIsAuthenticated] = useState<AuthEnum>(AuthEnum.PENDING);
    setIsAuthenticated(100) // no error, but should be

    return null
}

没有错误,但我们会期待。 这是因为没有推断出 enum 的值。

您可以查看我关于使用enums是一种更安全的方法的文章。

暂无
暂无

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

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