打字稿:取决于同一对象内另一个属性的属性类型

时间:2019-07-09 09:31:24

标签: typescript conditional-types

我有一个带有两个属性(type:stringargs:object)的TypeScript接口。 args可能具有不同的属性,具体取决于type。我需要对args应用哪种类型定义,以便编译器/自动完成将知道args允许使用哪些属性?

这有点类似于我在Redux中使用Actions的方式,后者确实具有typepayload,并且在我的化简器中,编译器通过切换语句知道有效载荷包含的内容。但是我无法使它与我的对象一起使用。 我在这里https://artsy.github.io/blog/2018/11/21/conditional-types-in-typescript/读了一篇很棒的文章,但这描述了一个具有两个args的方法的问题,两个args相互依赖,但是却不知道如何在同一个对象的两个属性上使它工作。

export interface IObject {
  type: ObjectType
  parameters: ObjectParameters
}
export type ObjectType = "check" | "counter"
export interface IParametersCheck {
  checked: boolean
}
export interface IParametersCounter {
  max: number
  min: number
  step: number
}
export type ObjectParameters = IParametersCheck | IParametersCounter

如果我有一个IObject并将类型设置为“检查”,则编译器/自动完成功能应提供IParametersCheck的属性。

1 个答案:

答案 0 :(得分:3)

我认为您真正要寻找的是一个受歧视的工会。 IObject本身应该是一个联合体:

export type IObject = {
    type: "checked"
    parameters: IParametersCheck
} | {
    type: "counter"
    parameters: IParametersCounter
}
export type ObjectType = IObject['type'] // in case you need this union
export type ObjectParameters = IObject['parameters'] // in case you need this union

export interface IParametersCheck {
    checked: boolean
}
export interface IParametersCounter {
    max: number
    min: number
    step: number
}

您也可以使用条件类型,但我认为联合解决方案效果更好:

export interface IObject<T extends ObjectType> {
    type: T
    parameters: T extends 'check' ? IParametersCheck: IParametersCounter
}

或具有映射界面:

export interface IObject<T extends ObjectType> {
    type: T
    parameters: ParameterMap[T]
}
type ParameterMap ={
    'check': IParametersCheck
    'counter': IParametersCounter
}

export type ObjectType = keyof ParameterMap