0

I want the option to have a path attribute or a children attribute, but not both. And can be correctly derived during use。

First, I do this:

type Option = {name: string, path: string} | {name: string, children: Option[]}
declare const option: Option
option.path // Property 'path' does not exist on type 'Test'

Online test

Then, I use this way: Does Typescript support mutually exclusive types?

type Without<T, U> = { [P in Exclude<keyof T, keyof U>]?: never };
type XOR<T, U> = (T | U) extends object ? (Without<T, U> & U) | (Without<U, T> & T) : T | U;


type Option = {name: string} & XOR<{path: string}, {children: Option[]}>

// const option: Option = {name: '1', path: ''} // ok
// const option: Option = {name: '1', children: []} // ok
// const option: Option = {name: '1', value: '', children: []} // error, but ok

declare const option: Option

if (option.children) option.children.concat()
else option.path.toLocaleUpperCase()

if (option.path) option.path.toLocaleUpperCase()
else option.children.concat() // why ?!

Online test

So, I want to know what is the reason for the above two errors? And how to fix them?

aweiu
  • 390
  • 4
  • 12

1 Answers1

1
type Option = {name: string, path?: never, children: Option[]} | {name: string, path: string, children?: never};


declare const option: Option

if (option.children) option.children.concat()
else option.path.toLocaleUpperCase()

if (option.path) option.path.toLocaleUpperCase()
else option.children.concat() //fixed

Hope this helps

EDIT You want discriminated union types, is essentially the true name for it. You can find the equivalent typescript documentation here https://www.typescriptlang.org/docs/handbook/advanced-types.html#discriminated-unions

Shanon Jackson
  • 5,873
  • 1
  • 19
  • 39
  • Thanks! But [Your method is wrong](https://www.typescriptlang.org/play/index.html#code/C4TwDgpgBA8mwEsD2A7KBeKBvFBDAthAFxQDOwATgigOYA0UYuwAFiShAG4QUMDGLBABsAJhQgoScRKgDaAXQC+UAD7Y8hEuSq0GTVlsrV6UAcLET2XHooDcAKEciIfIbnGnU5KEnjJJsH6ojr4yKAB0+izhwEgAyka0ABQAlFAA9OlQLL7QuGg8FEgU9qH+4Wai4hF8qHzMqRlZOZBQ+VCFxUA) – aweiu Sep 19 '19 at 10:11
  • `type Option = {name: string, path?: never, children: Option[]} | {name: string, path: string, children?: never};` – Shanon Jackson Sep 19 '19 at 10:26
  • [not fix](https://www.typescriptlang.org/play/index.html#code/C4TwDgpgBA8mwEsD2A7KBeKBvFBDAthAFxQDOwATgigOYA0UYuwAFgPwkoQBuEFDAYxYIANgBMKEFCTiJUAbQC6AXygAfbHkIlyVWgyasdlavShDREqRyhdeFZQG4AUK7EQBI3JPOpyUJHhkaVgg1FcEADMoAApAuRQAOgtxSRQASgCwpJSrHNQBZhj05wgRUmh44MTDFkTgJAAZJEKRCABVMEgKAGFcCuKI6LjsmuYWTKrUMdZ6ppbcNs7uvoGSsoqshOThVKlkgqLMgHpj2yRgKEiEAA8gA) – aweiu Sep 19 '19 at 10:58