TypeScript дискриминированный тип объединения с выводом по умолчанию и выводом типа - PullRequest
0 голосов
/ 04 января 2019

Я хочу создать Дискриминационный тип объединения, в котором не требуется передавать значение дискриминатора.

Вот мой текущий код:

interface Single<T> {
  multiple?: false // this is optional, because it should be the default
  value: T
  onValueChange: (value: T) => void
}

interface Multi<T> {
  multiple: true
  value: T[]
  onValueChange: (value: T[]) => void
}

type Union<T> = Single<T> | Multi<T>

Для тестирования я использую это:

function typeIt<T>(data: Union<T>): Union<T> {
    return data;
}

const a = typeIt({ // should be Single<string>
    value: "foo",
    onValueChange: (value) => undefined // why value is of type any?
})

const b = typeIt({ // should be Single<string>
    multiple: false,
    value: "foo",
    onValueChange: (value) => undefined
})

const c = typeIt({ // should be Multi<string>
    multiple: true,
    value: ["foo"],
    onValueChange: (value) => undefined
})

Но я получаю кучу ошибок и предупреждений ...:

  1. В const a onValueChange тип параметра value это any.При явной установке multiple: false (как в const b) он правильно выводится, поскольку string.

  2. const c вообще не работает.Я получаю эту ошибку: "Тип 'string' не может быть назначен типу 'string []'" .

У вас есть идеи, как решить эту проблему?

Я создал TypeScript Playground с этим кодом

1 Ответ

0 голосов
/ 04 января 2019

Я не думаю, что компилятор может легко определить тип параметра value в обратном вызове, так как тип литерала объекта все еще не определен при проверке обратного вызова.

Если вы неУ нас не так много членов профсоюза, и решение, которое работает должным образом, заключается в использовании нескольких перегрузок:

export interface Single<T> {
  multiple?: false // this is optional, because it should be the default
  value: T
  onValueChange: (value: T) => void
}

interface Multi<T> {
  multiple: true
  value: T[]
  onValueChange: (value: T[]) => void
}

type Union<T> = Single<T> | Multi<T>

function typeIt<T>(data: Single<T>): Single<T>
function typeIt<T>(data: Multi<T>): Multi<T>
function typeIt<T>(data: Union<T>): Union<T> {
    return data;
}

const a = typeIt({ // is Single<string>
    value: "foo",
    onValueChange: (value) => undefined // value is typed as expected
})

const b = typeIt({ // is Single<string>
    multiple: false,
    value: "foo",
    onValueChange: (value) => undefined
})

const c = typeIt({ // is be Multi<string>
    multiple: true,
    value: ["foo"],
    onValueChange: (value) => undefined
})
...