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

73

我有一个TypeScript接口,其中包含两个属性(type:stringargs:object)。根据type的不同,args可能具有不同的属性。我需要应用什么类型定义到args才能让编译器/自动完成知道哪些属性允许在args中使用?

这与我在Redux中使用的Actions有些相似,它们确实有一个type和一个payload,在我的reducer中,编译器通过switch语句知道payload包含了什么,但我无法让它在我的对象中正常工作。 我读了一篇很好的文章,在这里https://artsy.github.io/blog/2018/11/21/conditional-types-in-typescript/,但这只是描述了一个方法的两个参数之间如何相互依赖的问题,而不是如何让两个属性在同一个对象中正常工作。

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并将其类型设置为"check",编译器/自动完成应该提供IParametersCheck的属性。

1
似乎typeparameters之间没有连接,所以我不确定您是否可以设置此限制。也许在您创建操作的任何地方,您可以使用通用类型,并将其定义为IObject<ParameterType> - Icepickle
1个回答

113
我认为你实际上要寻找的是一个带标签联合类型。 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 'checked' ? IParametersCheck: IParametersCounter
}

或通过映射接口:

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

export type ObjectType = keyof ParameterMap

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接