繁体   English   中英

TypeScript,具有条件属性的通用类型

[英]TypeScript, generic type with conditional properties

我有一个这样的对象:

filters: Filters = {
  type: {
    name: 'type',
    type: FilterType.checkbox,
    availableValues: [
      { label: 'test 1', value: 1},
      { label: 'test 2', value: 2}
    ]
  },
  search: {
    name: 'search',
    type: FilterType.text,
  }
}

这代表了一些过滤器。 我有2个过滤器类型,一个过滤器可能需要一些额外的属性才能工作。 我想正确输入。 类型取决于type属性。

有什么想法吗? 我该怎么做?

您可以使用索引签名(以允许Filter任何键)和区分的联合类型要求某些搜索类型的额外属性:

type Filters = {
    [key: string]: {
        name: string,
        type: FilterType.checkbox,
        availableValues: Array<{
            label: string,
            value: number
        }>
    } | {
        name: string,
        type: FilterType.text,
    }
}

enum FilterType {
    checkbox,
    text
}
var filters: Filters = {
    type: {
        name: 'type',
        type: FilterType.checkbox,
        availableValues: [
            { label: 'test 1', value: 1 },
            { label: 'test 2', value: 2 }
        ]
    },
    search: {
        name: 'search',
        type: FilterType.text,
    }
}

或者,如果您想保留类型中的键并使用函数,也可以这样编写:

type Filters = {
    [key: string]: {
        name: string,
        type: FilterType.checkbox,
        availableValues: Array<{
            label: string,
            value: number
        }>
    } | {
        name: string,
        type: FilterType.text,
    }
}
enum FilterType {
    checkbox,
    text
}

function createFilter<T extends Filters>(p: T & { [P in keyof T]: { name : P }}) : T{
    return p
}

var filters =  createFilter({
    type: {
        name: 'type',
        type: FilterType.checkbox,
        availableValues: [
            { label: 'test 1', value: 1 },
            { label: 'test 2', value: 2 }
        ]
    },
    search: {
        name: 'search',
        type: FilterType.text,
    }
});

注意映射的类型{ [P in keyof T]: { name : P }}将强制执行以下事实,即name与对象分配给的key相同。 不知道这是否需要,但似乎是预期的用法。

我认为您正在尝试在此处封装过滤器类型和逻辑。 我猜测以下方法可能有用,以便您具有通用接口,并且可以对所有输入调用apply()方法。 虽然我不知道确切的用例。

export interface InputFilter {
  type: FilterType;
  apply: () => boolean;
}

export class CheckboxInputFilter implements InputFilter {
  type = FilterType.checkbox;
  availableValues: { label: string, value: number }[];

  apply(itemThatNeedFilter: any): boolean {
    // use this.availableValues and work out the instance filter result
  }
}

export class TextInputFilter implements InputFilter {
  type = FilterType.text;
  keyword: string;

  apply(itemThatNeedFilter: any): boolean {
    // use this.keyword and work out the instance filter result
  }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM