2

I want to call a function with an object as only argument. This object can be two different interfaces which collides (1+ properties have the same key but different possible values).

In my main function, I want to call getFoo if the type value in the object if foo and getBar if the type value in the object if bar.

interface Foo {
  title: string
  number: 1 | 2
}
interface FooWithType extends Foo {
  type: 'foo'
}

interface Bar {
  title: string
  number: 3 | 4
}
interface BarWithType extends Bar {
  type: 'bar'
}

function getFoo(params: Foo): void
function getBar(params: Bar): void

function main({ type, ...rest }: FooWithType | BarWithType) {
  return type === 'foo' ? getFoo(rest) : getBar(rest)
}

I have a TypeScript issue when I'm doing a conditional type on a destructured object where Type '{ title: string; number: 3 | 4; }' is not assignable to type 'Foo' because my rest value is still an union type when I typecheck it:

var rest: {
    title: string;
    number: 1 | 2;
} | {
    title: string;
    number: 3 | 4;
}

1 Answer 1

3

Typescript do not understand the rest type because it's destructured so uncorrelated to the type value. There's two possible ways to fix it without edit anything but the main function.

The first is type assertion (not recommended):

function main({ type, ...rest }: FooWithType | BarWithType) {
  return type === 'foo' ? getFoo(rest as Foo) : getBar(rest as Bar)
}

playground link


The second is to not destructure your object (better way):

function main(params: FooWithType | BarWithType) {
  return params.type === 'foo' ? getFoo(params) : getBar(params)
}

playground link

Sign up to request clarification or add additional context in comments.

Comments

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.