1

I have the following function:

type Option = {
  map?: {
    lat: number,
    lng: number
  }
  location?: boolean
}

const foo = (option: Option) => {
  if (option.map) {
    return {
      lat: option.map.lat,
      lng: option.map.lng,
    }
  } 

  if (option.location) {
    return 'location'
  }
}
  • if I call it with foo(), Typescript complains there should be 1 argument (as expected)
  • if I call it with foo({}), Typescript does not complain
  • I can call it with foo({ map: {lat: 1, lng: 1 }}) or foo({ location: true }) with no problems.

How can I tell typescript that the object HAS to have one of or map or location? So that foo({}) is not accepted?

The following question: is there a way to tell Typescript they are exclusive properties? Eg: if there's a map, there can't be a location and vice-versa?

Thanks a lot.

(I'm truly sorry if this is a duplicate. I can't even begin to think how to search this or what terms to use.)

Angelo Dias
  • 1,125
  • 4
  • 13
  • 23
  • 1
    Does [this](https://stackoverflow.com/questions/42123407/does-typescript-support-mutually-exclusive-types) help? –  May 13 '22 at 09:57
  • 1
    @T.J.Crowder that one does seem more fitting indeed :) –  May 13 '22 at 10:01
  • 1
    See the answers to the [linked question](https://stackoverflow.com/questions/37688318/typescript-interface-possible-to-make-one-or-the-other-properties-required). Basically, you can use a union of two types, one with `map` and one with `location`, and use a type guard (`"map" in option`) to determine which of the two you have. Here's that approach applied to your code: https://tsplay.dev/Na1XEN – T.J. Crowder May 13 '22 at 10:02
  • 1
    @T.J.Crowder While your example does seem to tell typescript the right thing, the function can still be called with `foo({ map: { lat: 0, lng: 0 }, location: true })` I'm not sure if the author of the question wanted the properties to be mutually exclusive or not. –  May 13 '22 at 10:10
  • @MikeS. - Good point. @​Angelo, the reason for what Mike says is that "excess" properties on instances of a type are allowed (except when you're using an object literal). The "except a literal" thing might make you think that having both `map` and `location` would mean one of them was "excess", but TypeScript allows all properties of the union's types. If you really want type-level mutual-exclusion, you'll have to take the slightly more complicated route from the answers [Mike pointed to](https://stackoverflow.com/questions/42123407/does-typescript-support-mutually-exclusive-types). – T.J. Crowder May 13 '22 at 10:33
  • Thank you very much for the resources and explanation. I'll take a look at everything. – Angelo Dias May 15 '22 at 08:30

0 Answers0