Home > Mobile >  TypeScript not correctly inferring Return type of Union
TypeScript not correctly inferring Return type of Union

Time:05-27

I don't know if this syntax is correct or there's a better way of doing it. I'm try to get TypeScript go correctly get the return type of a function that returns another function.

    type A = () => void;
    type B = (id: number) => void;
    type C = (id: number, title: string) => void;

    type D = A | B | C;
    interface Funcs {
      [key: string]: () => D
    }

Funcs is an object that contains a bunch of functions and it returns a function of Types A, B or C. For example:

 {
   addPerson: () => () => return add();
   deletePerson: (id) => () => return delete(id);
   updatePerson: (id, title) => () => return update(id, title
 }

When I try calling One of the functions. The signature of the return type is confused

CodePudding user response:

Your types and your object are different types. It is hard to understand which of two you exactly want, so there are few possible solutions.

  1. Assuming types are correct, editing object
type A = () => void;
type B = (id: number) => void;
type C = (id: number, title: string) => void;

type D = A | B | C;
interface Funcs {
  [key: string]: () => D
}

const Q: Funcs = {
    addPerson: () => () => {},
    deletePerson: () => (id) => {},
    updatePerson: () => (id, title) => {},
}

Q.updatePerson()(1, 'title') // example call
  1. Assuming object is correct, editing types
type A = () => () => void;
type B = (id: number) => () => void;
type C = (id: number, title: string) => () => void;

type D = A | B | C;
interface Funcs {
  [key: string]: D
}

const Q: Funcs = {
    addPerson: () => () => {},
    deletePerson: (id) => () => {},
    updatePerson: (id, title) => () => {},
}

Q.updatePerson(1, 'title')() // example call
  1. And simplest one, just in case you actually didn't want functions inside functions, because it doesn't seem it needs it..
type A = () => void;
type B = (id: number) => void;
type C = (id: number, title: string) => void;

type D = A | B | C;
interface Funcs {
  [key: string]: D
}

const Q: Funcs = {
    addPerson: () => {},
    deletePerson: (id) => {},
    updatePerson: (id, title) => {},
}

Q.updatePerson(1, 'title') // example call

Note, I used empty body function ({}) instead of your code for functions. It is hard to say why you do return delete(id); instead of just delete(id) in here, but it seems like it is reduced example.

CodePudding user response:

First of all, I have to define it correctly. Funcs is an interface that contains a dictionary definition. The value type of this dictionary object defined as follows;

() => D

where the type D is a union of;

type A = () => void;
type B = (id: number) => void;
type C = (id: number, title: string) => void;

type D = A | B | C;

That means, it will accept a function with the different argument bodies and returns nothing.

In your given example;

 {
   addPerson: () => () => return add();
   deletePerson: (id) => () => return delete(id);
   updatePerson: (id, title) => () => return update(id, title
 }

the return types for the given values matches with your union type(most probably, but we don't know the actual implementation of add, delete or update functions, I assume they return nothing), however the function parameters does not for any of the examples. To achieve what you wanna achive, you have to specify an additional type like so;

type X = () => D;
type Y = (id: number) => D;
type Z = (id: number, title: string) => D;

type T = X | Y | Z;


interface Funcs {
  [key: string]: T
}

Now, you have a dictionary type named T that accepts functions with 3 different argument body and each one of them returns another function with the type D.

  • Related