Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Typescript can't narrow function signature on sum type of component props

I have a component that takes two possible callbacks. The callback that should be passed depends on the other properties, if property type is passed with value A, then it should use callback A, if type is passed as B then it should use callback B. To express this dichotomy I am using a sum type for the entire props object, using the type as a tag.

I tried all kind of combinations for the tab, but I can not get TS to recognise that I’m passing the right callback.

Here is a simplification of the code:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

import React from 'react'
type SessionDefinition = {name: string}
type SessionDefinitionFromDb = {name: string, id: string}

type CreateCb = (definition: SessionDefinition) => Promise<void>;
type UpdateCb = (definition: SessionDefinitionFromDb) => Promise<void>;

type Props =
  | {
      isLoading: boolean;
      onSubmit: CreateCb;
      definition: SessionDefinition;
      action: 'create';
    }
  | {
      isLoading: boolean;
      onSubmit: UpdateCb;
      definition: SessionDefinitionFromDb;
      action: 'update';
    }

export default function DefinitionForm(props: Props) {
  return <div>'Test'</div>
}
<DefinitionForm 
isLoading
onSubmit={(x:SessionDefinitionFromDb) => console.log(x)}
definition={{ id: 'test', name:'text'}}
action='update'
/

The error typescript complains about is:

Type '(x: SessionDefinitionFromDb) => void' is not assignable to type 'CreateCb | UpdateCb'.
  Type '(x: SessionDefinitionFromDb) => void' is not assignable to type 'CreateCb'.
    Types of parameters 'x' and 'definition' are incompatible.
      Property 'id' is missing in type 'SessionDefinition' but required in type 'SessionDefinitionFromDb'.

And here is a Playground example

>Solution :

The error message is confusing, but the problem seems to come from the fact that your callback returns void, and not Promise<void> as expected. So replacing the said callback with (x: SessionDefinitionFromDb) => new Promise(() => console.log(x)) seems to solve it, as Typescript isn’t complaining anymore for me.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading