2

Given the following scenario,

function doSomething({ id, name, onSelect, onUnselect }: TDoSomething) {
  if (onSelect) {
    // I want `onUnselect` to be defined here
    // ...
  }

  return { id, name }
} 

type TDoSomething =
  | IDoSomethingWithoutSelect
  | IDoSomethingWithSelect

interface IDoSomethingWithoutSelect {
  id: string
  name: string
}

interface IDoSomethingWithSelect {
  id: string
  name: string

  onSelect: (id: string) => void
  onUnselect: (id: string) => void
}

What I want to do is (conceptually?) simple: want to have onUnselect to necessarily be defined if onSelect is. In other words, if I pass onSelect, then this function must expect a onUnselect as well.

(A playground to you can be accessed here.)

Turns out my attempts were failures. I don't know exactly what I should do to hit success.

(This is something else I've tried to do)

1 Answer 1

2

You can use in operator to narrow argument type to IDoSomethingWithSelect

function doSomething(arg: TDoSomething) {
  const { id, name } = arg;
  if ('onSelect' in arg) {
    arg.onUnselect(id);
  }

  return { id, name }
} 
Sign up to request clarification or add additional context in comments.

2 Comments

One side question, though. When I call doSomething({ onSelect: () => {} }) it doesn't require me to input onUnselect. Is there a way to overcome this?
Your example should fail with compilation error Argument of type '{ onSelect: () => void; }' is not assignable to parameter of type 'TDoSomething'.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.