网站搜索

如何在 Typescript 中将属性的类型设置为两个枚举的组合?


我有一个枚举:

enum EAlphabet = {
    A = 'A',
    B = 'B',
    C = 'C',
    D = 'D',
    E = 'E',
    F = 'F',
    G = 'G',
    H = 'H',
    I = 'I',
    J = 'J',
    K = 'K',
    L = 'L',
    M = 'M',
    N = 'N',
    O = 'O',
    P = 'P',
    Q = 'Q',
    R = 'R',
    S = 'S',
    T = 'T',
    U = 'U',
    V = 'V',
    W = 'W',
    X = 'X',
    Y = 'Y',
    Z = 'Z'
}

我有一个接口,我想给它的属性定义这样的类型:它可以是 'A'、'X'、'D' 中的一个,也可以是 'AA'、'JB'、'ZE' 中的一个,或者可以是 'ABC'、'ZJE' 中的一个。

我不确定该如何定义它,但可能是这样的?

interface foo {
    bar: EAlphabet + EAlphabet? + EAlphabet? /* What to do here? */
}

答案#1

首先,在这种情况下,我更倾向于使用字面量联合而不是枚举,这样使用起来会非常方便。不幸的是,你无法在类型级别进行字符串拼接,但你可以将表示方式改为元组,并获得所需的类型安全性。

所以我的解决方案恰好包含字面量联合,但将其与枚举一起使用的区别实际上很小。

type EAlphabet = 'A' | 'B' | 'C' | 'D'; // literal union instead of enum

interface Foo {
    bar: [EAlphabet] | [EAlphabet, EAlphabet] | [EAlphabet,EAlphabet,EAlphabet],
    toString: () => string
}

const makeFoo = (chars: Foo['bar']): Foo => ({
    bar: chars,
    toString: function () {
        return this.bar.join('');
    }
});

const example = makeFoo(['A', 'B']); // only max three allowed, works
console.log(example.toString()) // outputs AB

const example2 = makeFoo(['A', 'B', 'C', 'D']); // error wrong size
const example3 = makeFoo(['A', '*', 'C']); // error wrong sign

解决方案的要点是 [EAlphabet] | [EAlphabet, EAlphabet] | [EAlphabet, EAlphabet, EAlphabet] 我们定义该类型是包含 1、2 或 3 个元素的元组,不允许更多。顺便说一下,如果允许任意大小,那么类型应该只是 EAlphabet[]。

同样重要的是,我们可以创建值构造函数 - makeFoo,它可以创建一个有效的类型值,如你所见,我还添加了方便的函数 toString,它允许我们获取字符串表示形式。所以即使我们在底层使用元组,我们也可以在任何时候将其转换为 string。

使用枚举实现这一点将是相同的,唯一的区别是我们需要传递枚举值而不是普通字面量:

const example = makeFoo([EAlphabet.A, EAlphabet.B]); 

答案#2

枚举不是这样工作的,这也可能不是实现此目的的最佳方式。你可能需要将它定义为字符串,然后自己进行正则检查以查看它是否有 2-3 个字符等。

你可以(但你可能不应该)这样做。

// Array of EAlphabet with 2-3 Elements
export interface foo {
  [0]: EAlphabet;
  [1]: EAlphabet;
  [2]?: EAlphabet;
}

let a: foo;
a = [EAlphabet.A, EAlphabet.X, EAlphabet.D];

请记住

a = ['A', 'B']

这样还是不行。