Javascript 尝试至少显示一个可选参数是必需的,但其显示排除了其他参数

Javascript 尝试至少显示一个可选参数是必需的,但其显示排除了其他参数,javascript,typescript,types,Javascript,Typescript,Types,下面让我来举一个例子: type NodeOrMethod<T> = | { node?: Array<Filter<T>>; method: Condition<T>; } | { node: Array<Filter<T>>; method?: Condition<T>; }; inter

下面让我来举一个例子:

type NodeOrMethod<T> =
    | {
          node?: Array<Filter<T>>;
          method: Condition<T>;
      }
    | {
          node: Array<Filter<T>>;
          method?: Condition<T>;
      };

interface BaseFilter {
    label: string;
    value?: string;
}

export type Filter<T> = BaseFilter & NodeOrMethod<T>;
类型节点方法=
| {
节点?:数组;
方法:条件;
}
| {
节点:数组;
方法:条件;
};
接口基滤波器{
标签:字符串;
值?:字符串;
}
导出类型Filter=BaseFilter&nodeormmethod;

基本上,我想做的是使开发人员必须包括
节点
方法
——这是当前的工作方式;然而,我想进一步说,如果其中一个存在,另一个就不可能存在。因此,如果它们试图在同一个对象中同时包含
节点
方法
,它就会抱怨。以前有人做过类似的事情吗?

我可能会使用标记的联合(请参阅的相关部分)来完成您试图做的事情,例如

type Node<T> = {
    type: 'node',
    node: Array<Filter<T>>;
}
type Method<T> = {
    type: 'method',
    method: Condition<T>;
}
type NodeOrMethod<T> = Node<T> | Method<T>;

cost a: NodeOrMethod<T> = { // valid
  type: 'node',
  node: [...]
}

cost b: NodeOrMethod<T> = { // valid
  type: 'method',
  method: ...
}

cost c: NodeOrMethod<T> = { // type error
  type: 'method',
  node: [...],
  method: ...
}
类型节点={
类型:“节点”,
节点:数组;
}
类型方法={
类型:'方法',
方法:条件;
}
类型NodeOrMethod=节点|方法;
成本a:NodeOrMethod={//valid
类型:“节点”,
节点:[……]
}
成本b:NodeOrMethod={//valid
类型:'方法',
方法:。。。
}
成本c:nodeormmethod={//类型错误
类型:'方法',
节点:[……],
方法:。。。
}

我可能会使用带标签的联合体(请参阅的相关部分)来完成您尝试执行的操作,例如

type Node<T> = {
    type: 'node',
    node: Array<Filter<T>>;
}
type Method<T> = {
    type: 'method',
    method: Condition<T>;
}
type NodeOrMethod<T> = Node<T> | Method<T>;

cost a: NodeOrMethod<T> = { // valid
  type: 'node',
  node: [...]
}

cost b: NodeOrMethod<T> = { // valid
  type: 'method',
  method: ...
}

cost c: NodeOrMethod<T> = { // type error
  type: 'method',
  node: [...],
  method: ...
}
类型节点={
类型:“节点”,
节点:数组;
}
类型方法={
类型:'方法',
方法:条件;
}
类型NodeOrMethod=节点|方法;
成本a:NodeOrMethod={//valid
类型:“节点”,
节点:[……]
}
成本b:NodeOrMethod={//valid
类型:'方法',
方法:。。。
}
成本c:nodeormmethod={//类型错误
类型:'方法',
节点:[……],
方法:。。。
}

Node/JS哲学并不是这样的。对象被允许拥有任何他们想要的东西,而使用代码只关注它所关心的东西。一些处理方法包括:

  • 使用工厂方法确保对象的正确实例化
  • 具有指示是查看节点还是查看方法的“type”属性

尽管如此,该类型还是可疑地重载了两种含义。我希望有另一种模式可以避免这种情况。如果您被困在一个角落里,而代码不是您的,那么上述方法之一应该可以很好地工作。

Node/JS哲学并不是这样工作的。对象被允许拥有任何他们想要的东西,而使用代码只关注它所关心的东西。一些处理方法包括:

  • 使用工厂方法确保对象的正确实例化
  • 具有指示是查看节点还是查看方法的“type”属性


尽管如此,该类型还是可疑地重载了两种含义。我希望有另一种模式可以避免这种情况。如果您被困在一个角落,而代码不是您的,那么上述方法之一应该可以正常工作。

只需删除可选类型?@jonaswillms,它似乎不起作用。如果我同时添加节点和方法,它不会抱怨。我总是做
{type:“one”,stuff}{type:“two”,other}
,这样就行了。似乎联合类型就像一个“或”,只有当两种类型相互排斥时才是互斥的。如果你使用
方法:never
(不幸的是,我是AFK,所以我自己无法尝试)@Jonaswillms嗯,我从未使用过
never
,我只是尝试了一下,结果它炸了一些东西,但我可能会把它格式化得很奇怪。只需删除可选类型?@jonaswillms,这似乎不起作用。如果我同时添加节点和方法,它不会抱怨。我总是做
{type:“one”,stuff}{type:“two”,other}
,这样就行了。似乎联合类型就像一个“或”,只有当两种类型相互排斥时才是互斥的。如果你使用
方法:never
(不幸的是,我是AFK,所以我自己无法尝试)@Jonaswillms嗯,我从未使用过
never
,我只是尝试了一下,结果它炸了一些东西,但我可能会把它格式化得很奇怪。我觉得这个应该适合我,但由于某些原因它不是。它仍然允许出现
节点
方法
。当两者都不存在时,它只是抱怨。当然,我没有
type
属性。我添加了一个指向(简化的)游乐场演示“我没有type属性”的链接,这就是它相互排斥的原因。@Jonaswillms好的,所以我需要一个这样的属性来明确说明哪一个在那里?是的。但是我不知道union类型的实际语义是否能给出一个充分的答案(我仍然在等待那些ts goldbadger中的一个到达),但是例如,
{exists:true,stuff}{exists:false,other}
也会起作用,我觉得这对我来说应该起作用,但是出于某种原因它不起作用。它仍然允许出现
节点
方法
。当两者都不存在时,它只是抱怨。当然,我没有
type
属性。我添加了一个指向(简化的)游乐场演示“我没有type属性”的链接,这就是它相互排斥的原因。@Jonaswillms好的,所以我需要一个这样的属性来明确说明哪一个在那里?是的。但是我不知道联合类型的实际语义是否能给出一个充分的答案(我仍在等待一个ts goldbadger的到来),但是例如,
{exists:true,stuff}{exists:false,other}
也会起作用。在谈论Typescript时,您的第一段没有多大意义,因为对象确实有特定的形状。工厂方法将有助于加强某种形状,但适当的打字也是如此。“类型可能超载了”哦,这就是Typescript的全部内容。@Jonaswillms Typescri