Пересечение различаемых типов объединения

#typescript

#typescript

Вопрос:

Я пытаюсь создать пересечение различимых типов объединения. Попробовав множество различных способов, я обнаружил keyof оператор, который, похоже, сработал. Однако, когда я обобщаю оператор в частичную функцию, это не работает.

 class Account { ... }
type ILoggedIn =
  | { isLoggedIn: boolean; loggedInUser?: any }
  | { isLoggedIn: false; loggedInUser?: undefined }
  | { isLoggedIn: true; loggedInUser?: any }

type IInitialized =
  | { initialized: boolean; account?: undefined }
  | { initialized: false; account?: undefined }
  | { initialized: true; account?: Account }

type IContextWorks = { [K in keyof ILoggedIn]?: ILoggedIn[K] } amp;
  { [K in keyof IInitialized]?: IInitialized[K] }

type Partial<T> = { [P in keyof T]?: T[P] }
type IContextNotWork = Partial<ILoggedIn> amp; Partial<IInitialized>

const valueWorks: IContextWorks = {
  account: new Account(),
  initialized: true,
  isLoggedIn: true,
  loggedInUser: {},
}
const valueNotWork: IContextNotWork = {
  account: new Account(),
  initialized: true,
  isLoggedIn: true,
  loggedInUser: {},
}
  

Ошибка, которую я получаю при использовании NotWork версии, является:

 Type 'boolean' is not assignable to type 'true | undefined'.
  

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

Что я сделал не так?

Комментарии:

1. Что такое IXyaInitialized ? И я не могу воспроизвести вашу ошибку.

2. Кроме того, IContextWorks больше не является различаемым объединением. Различаемое объединение: {kind: "s", value: string} | {kind: "n", value: number} . Нет: {kind: "s" | "n", value: string | number} . В частности, значение типа {kind: "s", value: 7} соответствует последнему типу, но не первому типу.

3. Насколько я понимаю, вы пытаетесь создать объединение из 9 типов пересечения, верно?

4. Вы могли бы использовать различаемые объединения для этого, но на самом деле, если вы ищете только существование свойства, вам не нужно хранить для него отдельное логическое значение, вы можете просто вычислить это логическое значение, когда вам это нужно … (например, typeof value.account !== 'undefined' )

5. Если вы не можете воспроизвести проблему в автономной среде, то, я полагаю, ваш следующий шаг — проанализировать среду, в которой вы видите ошибку, и попытаться выяснить, что отличается. Если ошибка возникает только в определенной версии TypeScript или с определенным набором опций компилятора, то это имеет отношение к вопросу и должно быть отредактировано. Удачи!

Ответ №1:

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

 type UnionOfIntersections =
    | { isLoggedIn: boolean; loggedInUser?: any } amp; { initialized: boolean; account?: undefined }
    | { isLoggedIn: boolean; loggedInUser?: any } amp; { initialized: false; account?: undefined }
    | { isLoggedIn: boolean; loggedInUser?: any } amp; { initialized: true; account?: Account }
    | { isLoggedIn: false; loggedInUser?: undefined } amp; { initialized: boolean; account?: undefined }
    | { isLoggedIn: false; loggedInUser?: undefined } amp; { initialized: false; account?: undefined }
    | { isLoggedIn: false; loggedInUser?: undefined } amp; { initialized: true; account?: Account }
    | { isLoggedIn: true; loggedInUser?: any } amp; { initialized: boolean; account?: undefined }
    | { isLoggedIn: true; loggedInUser?: any } amp; { initialized: false; account?: undefined }
    | { isLoggedIn: true; loggedInUser?: any } amp; { initialized: true; account?: Account }
  

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

 type IContextNotWork = Partial<ILoggedIn> amp; Partial<IInitialized>
  

Комментарии:

1. Есть ли способ увидеть, как выглядит тип конечного результата объединения / пересечения, или единственный способ сделать это — провести некоторое модульное тестирование?

2. ts-игроваяплощадка . Я всегда сначала пробую что-то там. наведение курсора мыши может сообщить много полезной информации