拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 反应打字稿:使用“Object.freeze”(列举)作为型别

反应打字稿:使用“Object.freeze”(列举)作为型别

白鹭 - 2022-03-16 1972 0 0

我有这个“列举”:

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);

是否有可能以某种方式表明状态的型别是 AuthEnum?

uj5u.com热心网友回复:

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

const [isAuthenticated, setIsAuthenticated] = useState<typeof AuthEnum>(AuthEnum.PENDING); 不起作用,因为typeof AuthEnum它是一个物件,而您传递的 AuthEnum.PENDING是一个数字。

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

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 实用程序型别回传所有??物件值的联合。


没有as const AuthEnum变得公正:

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

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

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

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

这就是为什么问题的作者使用不可变物件而不是enum. 既然你只有 3 个属性:1, 2, 3你为什么允许setIsAuthenticated使用任何其他自变量呼叫函式?很明显,呼叫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是一种更安全的方式的文章。

标签:

0 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *