类型定义:如何键入数组以同时没有两个特定值
Type Definition : How to type an array to don't have tow specific value at the same time
我想创建一个只能具有这些特定值而没有其他值的类型:
[0,1],[1,1],[1,0],[1,-1],[0,-1],[-1,-1],[-1,0],[-1,1]
为了实现这一点,我做了这个类型定义:
type Steps = -1 | 0 | 1;
type Directions = [width:Steps, height:Steps];
但是有了这个定义,我可以做到:
const invalidDirection : Directions = [0,0];
而且我不知道如何限制它,尤其是 [0,0]
。
没有单一的、特定的tuple type that corresponds to your intended Directions
. The single specific tuple type [width: Steps, height: Steps]
will, by necessity, allow the first element (labeledwidth
)独立于第二个元素(标记为height
)被选择。因此,没有什么能阻止人们为这两个元素选择 0
。
如果你想让两个元素相互依赖,你应该把Directions
写成union可接受的类型。您可以手动执行此操作,或者
type Directions = [width: Steps, height: Exclude<Steps, 0>] |
[width: Exclude<Steps, 0>, height: Steps];
或
type Directions = [width: 0, height: Exclude<Steps, 0>] |
[width: Exclude<Steps, 0>, height: 0] |
[width: Exclude<Steps, 0>, height: Exclude<Steps, 0>];
或
type Directions = [width: 0, height: 1] | [width: 0, height: -1] |
[width: 1, height: 0] | [width: 1, height: 1] |
[width: 1, height: -1] | [width: -1, height: 0] |
[width: -1, height: 1] | [width: -1, height: -1];
(请注意,虽然所有这三个都对应于同一组静态
值,它们不被编译器认为是相互等价的,并且可能在不同的上下文中表现出不同的行为;参见 进行一些讨论)
任何这些都会导致所需的行为:
let dir: Directions;
dir = [0, -1]; // okay
dir = [1, -1]; // okay
dir = [1, 0]; // okay
dir = [1, 1]; // okay
dir = [0, 1]; // okay
dir = [-1, 1]; // okay
dir = [-1, 0]; // okay
dir = [-1, -1]; // okay
dir = [0, 0]; // error!
前两种方法使用 the Exclude<T, U>
utility type 从联合中过滤类型。请注意,第一个足够简洁,您可以决定直接使用它。
另一方面,您可能希望根据 Steps
的定义 以编程方式 执行此操作,而不是手动...尤其是当您关心缩放工会或改变他们的价值观。这是一种方法:
type Directions = Exclude<
{ [W in Steps]: {
[H in Steps]: [width: W, height: H] }[Steps]
}[Steps], [0, 0]>;
我们正在 Exclude
-ing 表达式 {[W in Steps]....}
中的坏 [0, 0]
成员,所以让我们检查一下。在这里,我正在制作一个嵌套的“分布式对象类型”(如 microsoft/TypeScript#47109), which is making a mapped type and then immediately indexing into it 中定义的那样,以获得联合。让我们看一下内部的,{[H in Steps]: [width: W, height: H]}[Steps]
:
映射类型在 Steps
的每个联合成员上迭代 H
并创建一个新的 three-keyed 对象类型,如 {"-1": [width: W, height: -1], "0": [width: W, height: 0], "1": [width: W, height: 1]}
。然后我们使用索引 [-1 | 0 | 1]
索引到该对象类型,它产生 three-member 联合 [width: W, height: -1] | [width: W, height: 0] | [width: W, height: 1]
。您有望看到外部分布式对象类型如何为 W
插入 -1
、0
和 1
并生成 nine-element 联合。
回想一下,我们 Exclude
来自该联合的 [width: 0, height: 0]
元素以获得您想要的 eight-element 联合!
我想创建一个只能具有这些特定值而没有其他值的类型:
[0,1],[1,1],[1,0],[1,-1],[0,-1],[-1,-1],[-1,0],[-1,1]
为了实现这一点,我做了这个类型定义:
type Steps = -1 | 0 | 1;
type Directions = [width:Steps, height:Steps];
但是有了这个定义,我可以做到:
const invalidDirection : Directions = [0,0];
而且我不知道如何限制它,尤其是 [0,0]
。
没有单一的、特定的tuple type that corresponds to your intended Directions
. The single specific tuple type [width: Steps, height: Steps]
will, by necessity, allow the first element (labeledwidth
)独立于第二个元素(标记为height
)被选择。因此,没有什么能阻止人们为这两个元素选择 0
。
如果你想让两个元素相互依赖,你应该把Directions
写成union可接受的类型。您可以手动执行此操作,或者
type Directions = [width: Steps, height: Exclude<Steps, 0>] |
[width: Exclude<Steps, 0>, height: Steps];
或
type Directions = [width: 0, height: Exclude<Steps, 0>] |
[width: Exclude<Steps, 0>, height: 0] |
[width: Exclude<Steps, 0>, height: Exclude<Steps, 0>];
或
type Directions = [width: 0, height: 1] | [width: 0, height: -1] |
[width: 1, height: 0] | [width: 1, height: 1] |
[width: 1, height: -1] | [width: -1, height: 0] |
[width: -1, height: 1] | [width: -1, height: -1];
(请注意,虽然所有这三个都对应于同一组静态
值,它们不被编译器认为是相互等价的,并且可能在不同的上下文中表现出不同的行为;参见
任何这些都会导致所需的行为:
let dir: Directions;
dir = [0, -1]; // okay
dir = [1, -1]; // okay
dir = [1, 0]; // okay
dir = [1, 1]; // okay
dir = [0, 1]; // okay
dir = [-1, 1]; // okay
dir = [-1, 0]; // okay
dir = [-1, -1]; // okay
dir = [0, 0]; // error!
前两种方法使用 the Exclude<T, U>
utility type 从联合中过滤类型。请注意,第一个足够简洁,您可以决定直接使用它。
另一方面,您可能希望根据 Steps
的定义 以编程方式 执行此操作,而不是手动...尤其是当您关心缩放工会或改变他们的价值观。这是一种方法:
type Directions = Exclude<
{ [W in Steps]: {
[H in Steps]: [width: W, height: H] }[Steps]
}[Steps], [0, 0]>;
我们正在 Exclude
-ing 表达式 {[W in Steps]....}
中的坏 [0, 0]
成员,所以让我们检查一下。在这里,我正在制作一个嵌套的“分布式对象类型”(如 microsoft/TypeScript#47109), which is making a mapped type and then immediately indexing into it 中定义的那样,以获得联合。让我们看一下内部的,{[H in Steps]: [width: W, height: H]}[Steps]
:
映射类型在 Steps
的每个联合成员上迭代 H
并创建一个新的 three-keyed 对象类型,如 {"-1": [width: W, height: -1], "0": [width: W, height: 0], "1": [width: W, height: 1]}
。然后我们使用索引 [-1 | 0 | 1]
索引到该对象类型,它产生 three-member 联合 [width: W, height: -1] | [width: W, height: 0] | [width: W, height: 1]
。您有望看到外部分布式对象类型如何为 W
插入 -1
、0
和 1
并生成 nine-element 联合。
回想一下,我们 Exclude
来自该联合的 [width: 0, height: 0]
元素以获得您想要的 eight-element 联合!