Typescript - 当传入多个键值时缩小函数中的 T[K]

标签 typescript generics

我正在尝试编写一个钩子(Hook),它接受对象的多个键并根据当前应用的过滤器过滤数据。所以,大致如下:

interface IFilterable<T,K extends keyof T & string>{
  key: K;
  customFilter?: (item: T[K], applied: T[K][]) => boolean
  //The hook uses some default logic to filter if this function isn't available.
}

function useFilters<T,K extends keyof T & string>(data: T[], filters: IFilterable<T,K>[]): T[]{
 //filter out the data, return new dataset.
}

问题在于,当传入多个过滤器 (IFilterable) 时,customFilter< 中的 itemapplied 参数 函数成为键类型的并集。或者,在代码中...

useFilters(
  [{a: 1, b: "bob"], {a: 2, b: "berry"}],
  [{key: "a", customFilter: (item, applied) => {
    //Wanted: item has the type number
    //Reality: item has the type (string | number)
  }, 
  {key: "b", customFilter: (item, applied) => {
    //Wanted: item has the type string.
    //Reality: item has the type (string | number)
  }
}]);

我通过将所有内容输入为 unknown(或 unknown[]),然后创建包装函数,稍后将其转换回正确的类型,“解决”了这个问题,但如果可能的话,我希望自始至终都保持强类型。

那么,在这种情况下,我传递对象数组,其中一个属性是键,另一个属性是采用 T[K] 的函数,有什么办法可以缩小范围转换为特定 T[K] 的类型而不是联合类型?

谢谢。

最佳答案

2021 年 9 月 17 日更新

我做了作业。

考虑这个例子:

/**
 * Obtain a union of all values of a dictionary
 */
type Values<T> = T[keyof T]

type FilterBuilder<T extends any[]> = Values<{
  [Key in keyof T[number]]: {
    key: Key,
    customFilter: (item: T[number][Key], applied: T[number][Key][]) => void
  }
}>

{
  //   type Test = {
  //     key: "a";
  //     customFilter: (item: 1, applied: 1[]) => void;
  // } | {
  //     key: "b";
  //     customFilter: (item: "str", applied: "str"[]) => void;
  // }
  type Test = FilterBuilder<[{ a: 1, b: 'str' }]>
}

const withFilters = <
  Item extends Record<PropertyKey, unknown>,
  Items extends Item[],
  >(data: [...Items]) => <
    Filter extends FilterBuilder<Items>,
    Filters extends Filter[],
    >(filters: [...Filters]) => { }

const useFilters = withFilters([{ a: 1, b: "bob" }, { a: 2, b: "berry" }])

const result = useFilters(
  [{
    key: "a", customFilter: (item, applied) => { }
  },
  {
    key: "b", customFilter: (item, applied) => { }
  }]
);

typescript 很难推断出对象的key并将该类型立即应用于同一对象的另一个属性,至少在这种情况下是这样。

因此,我刚刚创建了所有允许的 key/customFilter 过滤器对的并集。

Playground

Values - 创建字典数据结构的所有值的并集

FilterBuilder:

  1. 迭代元组T中存在的元素的每个键。
  2. 使用 keycustomFilter 属性为迭代键创建一个新对象。
  3. 其中 customFilter 是一个具有两个参数的函数:item - 迭代对象的值,applied - 迭代对象的值数组<

withFilters:是一个柯里化(Currying)函数。它需要我们感兴趣的对象元组,并返回需要 FilterBuilder 结果数组的函数。 FilterBuilder 仅返回 key/customFilter 对象所有允许状态的可区分联合。

关于Typescript - 当传入多个键值时缩小函数中的 T[K],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63708358/

相关文章:

javascript - 如何将可选链接与数组和函数一起使用?

javascript - 解构嵌套对象 es6

c# - C#中的通用缓存

java - Java 泛型中的错误 - 所需类型 : List<MyClass> Provided: List<T>

java - 在不知 Prop 体类型的情况下实例化对象

c# - 具有泛型类型的接口(interface)中的枚举返回函数出错

java - 我必须分配什么编译时类型来接收 java.util.Map<TextAttribute, ?> 的返回值

javascript - 类型 'selectionStart' 上不存在属性 'EventTarget'

javascript - 如何为 Polymer 3.x 导入 <paper-textarea>?

angularjs - AngularJS $routeProvider 模块的 TypeScript 示例