我可以从属性的实现中获取泛型吗?

时间:2019-09-17 02:33:32

标签: typescript

我有以下对象(仅用于测试):

{
  type: 'custom',
  source: (): number[] => { return [1,2,3,4] },
  filters: [
    {
      text: 'Is in one of',
      value: 'iiof',
      action: (v: MainType, k: number[]) => true
    },
    {
      text: 'Is not in one of',
      value: '!iiof',
      action: (v: MainType, k: number[]) => true
    }
  ]

}

我正在尝试构建类型,以便任何filter.action函数的第二个参数将是source的返回类型。我可以使用any,但希望尽可能键入此类型。

我当前的类型如下:

export type FilterCustomImpl<T, K> = {
  text: string;
  value: string;
  action: (v: T, s: K[]) => boolean;
};

export type FilterCustomSchemaField<T, K = any> = {
  type: 'custom',
  display?: string;
  source: () => K[];
  filters: FilterCustomImpl<T, K>[]
};

export type FilterSchemaField<T> = 
    FilterEnumSchemaField | 
    FilterNumericSchemaField | 
    FilterStringSchemaField | 
    FilterCustomSchemaField<T>;

export type FilterSchemaFields<T> = { [index: string]: FilterSchemaField<T> };

export type FilterSchema<T> = {
  defaultKey: string;
  fields: FilterSchemaFields<T>
};

因此,父FilterSchema可以有无限数量的FilterCustomSchemaField,具有不同的K类型。

目前,在构建过滤器架构时,我可以通过在字段本身上指定类型来解决它,所以

{
  type: 'custom',
  source: (): number[] => { return [1,2,3,4] },
  filters: [
    {
      text: 'Is in one of',
      value: 'iiof',
      action: (v: MainType, k: number[]) => true
    },
    {
      text: 'Is not in one of',
      value: '!iiof',
      action: (v: MainType, k: number[]) => true
    }
  ]
} as FilterCustomSchemaField<MainType, number>

但这不是一个好方法,因为它显然需要额外的输入,并且每次都必须重写主要的T类型。

如果我可以从K函数的返回类型中推断出source类型,那将是理想的选择,但我不确定是否可行。

1 个答案:

答案 0 :(得分:1)

我可能会使用curried辅助函数(这种做法是为了解决缺少partial type parameter inference的问题,有关更多详细信息,请参见this answer),以便您可以手动指定{{1 }}一次,并让编译器推断T的值。 (我知道您将其称为U,但是习惯上是KK用于键类型,而PT用于键类型。一般类型...并且由于您不将其限制为类似U之类的键类型,因此我将更改名称。)

这里是:

string | number | symbol

这是它的用法:

const asFilterCustomSchemaField = <T>() => <U>(
  x: FilterCustomSchemaField<T, U>
) => x;

请注意,值如何根据需要设置为const filterCustomSchemaField = asFilterCustomSchemaField<MainType>()({ type: "custom", source: () => [1, 2, 3, 4], filters: [ { text: "Is in one of", value: "iiof", action: (v, k) => true // v is inferred as MainType, k as number[] }, { text: "Is not in one of", value: "!iiof", action: (v, k) => true // v is inferred as MainType, k as number[] } ] }); // const filterCustomSchemaField: FilterCustomSchemaField<MainType, number> 类型,其中仅从值中推断出FilterCustomSchemaFiled<MainType, number>,并指定了number。如果您使用IntelliSense并将鼠标悬停在MainType属性中的vk上,您也会看到它们分别被推断为actionMainType

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

Link to code