Home > Back-end >  How can I determine the type of another property of same object according to the property's val
How can I determine the type of another property of same object according to the property's val

Time:03-02

I have the types as follows:

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[];

What I am trying to do is define the Filter type by the Operators type.

If the user specifies Operators as "or" then the field property is not required and the value property is Filters type. As follows:

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

If the user specifies Operators other than "or" then the field property is required and the value property is any type. As follows:

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

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

CodePudding user response:

You can define the Filters type as Union type array to switch between your type conditions.

/** 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)[];

So when you can use Filters type like this;

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" }] }];

CodePudding user response:

If you use Enums you can make field required if the Operator equals 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
}
  • Related