【问题标题】:Typescript - Narrowing T[K] in a function when multiple key values are passed inTypescript - 传入多个键值时缩小函数中的 T[K]
【发布时间】:2021-09-17 20:53:49
【问题描述】:

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

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] 的函数,以缩小到特定@987654330 的类型@ 而不是联合类型?

谢谢。

【问题讨论】:

  • IFilterable 的接口错误。 TS 没有像 (item: T[K], applied: T[K][])这样的元组类型
  • @captain-yossarian 这是一个返回布尔值的函数......我忘了在那里添加返回类型。更新了原帖。

标签: typescript generics


【解决方案1】:

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) => { }
  }]
);

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

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

Playground

Values - 创建字典数据结构的所有值的联合

FilterBuilder

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

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

【讨论】:

  • 对不起,但这确实不能回答我的问题。我知道为什么会发生这种情况,但是我不想只使用一个键 - 关键是能够传入多个具有不同过滤功能的键来缩小范围原始数据集。我正在寻找的是,当有多个 K 值时,是否有办法缩小 T[K] 的范围,以便每个 customFilter 函数都可以使用与其分组的键正确键入。
  • @ChristopherOpiela 进行了更新
猜你喜欢
  • 2020-01-15
  • 1970-01-01
  • 2019-02-02
  • 2018-12-27
  • 2019-08-03
  • 2018-05-30
  • 2022-12-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多