Определить объединение свойств машинописного текста из универсального типа аргумента - PullRequest
0 голосов
/ 24 сентября 2019

У меня есть несколько видов операций фильтрации

type FilterOp = 'Equals' | 'NotEquals' | 'Greater' | 'GreaterEqual' | 'Less' | 'LessEqual';
type ArrayFilterOp = 'In' | 'NotIn';
type StringFilterOp = 'StartsWith' | 'EndsWith' | 'Contains' | 'NotContains';
type DateFilterOp = 'DateIn' | 'DateNotIn'

, и это мое текущее определение фильтра

type GenericFilter<T> = {
    Property: string,
    Value: T,
    Operation: FilterOp | ArrayFilterOp | StringFilterOp | DateFilterOp
}

Можно ли как-то определить тип Operation на основе Tаргумент?Например, если мой T равен Date, тогда машинопись позволит только DateFilterOp и FilterOp присваивать Operation свойство

let dateFilter: GenericFilter<Date> = {
    Property: "DateCreated",
    Value: new Date(),
    Operation: // now I can only set value from FilterOp or DateFilterOp
}

Ответы [ 2 ]

1 голос
/ 24 сентября 2019

При условии, что я правильно понимаю ограничение, вы можете использовать условные типы для его представления:

type Operation<T> =
  | FilterOp
  | (T extends Array<any> ? ArrayFilterOp : never)
  | (T extends string ? StringFilterOp : never)
  | (T extends Date ? DateFilterOp : never);

type GenericFilter<T> = {
  Property: string;
  Value: T;
  Operation: Operation<T>;
};

Это поддержит ваш заявленный вариант использования:

let dateFilter: GenericFilter<Date> = {
  Property: "DateCreated",
  Value: new Date(),
  Operation: "DateIn"
};

а также работа с вспомогательной функцией, так что вы можете просто сделать вывод T вместо указания ее вручную:

const asGenericFilter = <T>(filt: GenericFilter<T>) => filt;

let stringFilter = asGenericFilter({
  Property: "Name",
  Value: "Alice",
  Operation: "StartsWith" // hinted as Operation<string>
})

Надеюсь, что это поможет;удачи!

Ссылка на код

0 голосов
/ 24 сентября 2019

Мне удалось реализовать решение через OperationMap

type OperationMap<T> = 
    T extends Date
        ? (DateFilterOp | FilterOp)
        : T extends Array<any>
            ? ArrayFilterOp
            : T extends String
                ? FilterOp | StringFilterOp
    : FilterOp;

type GenericFilter<T> = {
    Property: string,
    Value: T,
    Operation: OperationMap<T>
}
...