如何根据对象的 属性 的值判断同一对象的另一个 属性 的类型?

How can I determine the type of another property of same object according to the property's value of the object?

我有以下类型:

type Operators =
    | "eq"
    | "ne"
    | "lt"
    | "gt"
    | "lte"
    | "gte"
    | "in"
    | "nin"
    | "contains"
    | "ncontains"
    | "containss"
    | "ncontainss"
    | "between"
    | "nbetween"
    | "null"
    | "nnull"
    | "or"

type Filter = {
    field: string;
    operator: Operators;
    value: any
};

export type Filters = Filter[];

我想做的是通过 Operators 类型定义 Filter 类型。

如果用户将 Operators 指定为 "or",则 field 属性 不是必需的,value 属性 是 Filters 类型。如下:

export type Filter = {
    field: string | undefined;
    operator: Operators;
    value: Filters;
};

如果用户指定 Operators 而不是 "or",则 field 属性 是必需的,value 属性 是 any 类型。如下:

export type Filter = {
    field: string;
    operator: Operators;
    value: any
};

如何根据属性对象的值判断另一个属性对象的类型?

如果您使用枚举,您可以在运算符等于 Or 时将字段设为必填。

enum Operators {
  Eq = "eq",
  Ne = "ne",
  Or = "or"
}

type Filter = {
    field: string;
    operator: Operators.Or;
    value: any
} | type Filter = {
    field: string;
    operator: Operators.Or;
    value: any
} | {
    field?: string;
    operator: Exclude<Operators, Operators.Or>
    value: any
};

// field is required
const filterOr: Filter = {
    field: 'field', 
    value: 'string',
    operator: Operators.Or
}

// field is not required
const filterEq: Filter = {
    value: 'string',
    operator: Operators.Eq
}

const filterEe: Filter = {
    value: 'string',
    operator: Operators.Ne
}

您可以将 Filters 类型定义为 Union 类型数组以在您的类型条件之间切换。

/** Separating the operators type into two; not fully needed but easier to understand imo **/

type LogicalOperators = 
    | "eq"
    | "ne"
    | "lt"
    | "gt"
    | "lte"
    | "gte"
    | "in"
    | "nin"
    | "contains"
    | "ncontains"
    | "containss"
    | "ncontainss"
    | "between"
    | "nbetween"
    | "null"
    | "nnull";


type ConditionalOperators = "or" | "and";

/** Intersect these two type, so you can reference it easier later. **/
type Operators = LogicalOperators & ConditionalOperators;

/** Checking the value by the operator and field **/
type LogicalFilter = {
    field: string;
    operator: LogicalOperators;
    value: any
};

/** Combining filters with `or` or `and` **/
type ConditionalFilter = {
    operator: ConditionalOperators;
    value: Filters;
}

/** Define the Filters type as a union **/
type Filters = (LogicalFilter | ConditionalFilter)[];

因此,当您可以使用 Filters 时,请这样输入;

const isApple: Filters = [{ field: "fruitName", operator: "eq", value: "Apple" }];

const isAppleOrPear: Filters = [{ operator: "or", value: [{ field: "fruitName", operator: "eq", value: "Apple" }, { field: "fruitName", operator: "eq", value: "Pear" }] }];