【问题标题】:Determine typescript property union from generic argument type从通用参数类型确定打字稿属性联合
【发布时间】:2019-09-25 01:16:40
【问题描述】:

我有一些过滤操作

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 类型?例如,如果我的TDate,那么打字稿将只允许将DateFilterOpFilterOp 分配给Operation 属性

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

【问题讨论】:

    标签: typescript typescript-typings typescript-generics


    【解决方案1】:

    假设我正确理解了约束,您可以使用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>
    })
    

    希望有所帮助;祝你好运!

    Link to code

    【讨论】:

    • 是的,我已经实现了类似的东西,但是你的更干净一些,谢谢你的努力!
    【解决方案2】:

    我已经通过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>
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-05
      • 2016-07-07
      • 2020-05-21
      • 2017-05-18
      相关资源
      最近更新 更多