Взаимно включающие типы в TypeScript - PullRequest
0 голосов
/ 16 июня 2020

Мне нужно express идея о том, что «если одно из этих полей существует, то существует и другое». Естественно, если эти два поля являются одноранговыми узлами в одной и той же области, тогда становится трудно представить эту идею.

Например, учитывая тип Pipeline:

type Status = 'running' | 'finished' | 'error' | 'inherited'
type Pipeline = Array<{
    name: string
    status: Status
    parent?: string // dirty. only 'inherited' needs this.
}>

Как Вы представляете идею, что поле parent должно быть определено, если status='inherited'?

Ответы [ 2 ]

2 голосов
/ 16 июня 2020

В зависимости от того, каков именно ваш вариант использования, вы также можете рассмотреть условные типы, например

type Status = 'running' | 'finished' | 'error' | 'inherited'

type Pipeline<S extends Status> = Array<{
    name: string
    status: S
    parent: S extends 'inherited' ? string : never
}>

declare const a: Pipeline<'inherited'>
declare const b: Pipeline<'finished'>
a[0].parent // string
b[0].parent // never
1 голос
/ 16 июня 2020

Вместо того, чтобы думать о «взаимном включении» этих параметров вместе, лучше думать об этом как об «изгнании их» от других.

type Status = 'running' | 'finished' | 'error' | 'inherited'
type Pipeline = Array<{
    name: string
    status: Exclude<Status, 'inherited'>
} | {
    name: string
    status: 'inherited'
    parent: string
}>

Конечно, для более сложных схем , это имеет тот недостаток, что теперь вам нужно повторять множество полей.

Чтобы справиться с этим, вы можете собрать общие поля и наследовать от них с помощью оператора &.

type Common = {
    name: string
    lots: string
    of: string
    metadata: string
}
type Pipeline = Array<Common & ({
    status: Exclude<Status, 'inherited'>
} | {
    status: 'inherited'
    parent: string
})>

Хотя это поможет в проверке типов, абстракция делает фактический тип более непрозрачным в окне проверки ошибок.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...