从通用参数类型确定打字稿 属性 联合
Determine typescript property union from generic argument type
我有一些过滤操作
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
}
是否可以根据 T
参数以某种方式确定 Operation
类型?例如,如果我的 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
}
我已经通过 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>
}
假设我正确理解约束,你可以使用 conditional types 来表示它:
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>
})
希望对您有所帮助;祝你好运!
我有一些过滤操作
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
}
是否可以根据 T
参数以某种方式确定 Operation
类型?例如,如果我的 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
}
我已经通过 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>
}
假设我正确理解约束,你可以使用 conditional types 来表示它:
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>
})
希望对您有所帮助;祝你好运!