Typescript: тип свойства, зависящего от другого свойства в том же объекте - PullRequest
1 голос
/ 09 июля 2019

У меня есть интерфейс TypeScript с двумя свойствами (type:string и args:object). args может иметь различные свойства в зависимости от type. Какое определение типа мне нужно применить к args, чтобы компилятор / автозаполнение знал, какие свойства разрешены для args?

Это несколько похоже на то, как я использую Actions в Redux, который имеет type и payload, и в моем редукторе компилятор знает по инструкции switch, что содержит полезная нагрузка. Но я не могу заставить это работать с моим объектом. Я прочитал отличную статью здесь 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 Ответ

3 голосов
/ 09 июля 2019

Я думаю, что вы на самом деле ищете дискриминационный союз.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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...