Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript interface: Not all constituents of type 'string | (() => string)' are callable. Type 'string' has no call signatures

interface ExampleType {
  [key: string]: string | (() => string);
}

const testObj: ExampleType = {
  firstName: "Peter",
  lastName: "Parker",
  gender: "male",
  getFullName: () => "I am Peter Parker",
};

const { firstName, lastName, getFullName } = testObj;


console.log(getFullName()); // this does  not works

if (typeof getFullName === "function") {
    console.log(getFullName()) // this works
}

I am getting following error: **This expression is not callable. Not all constituents of type 'string | (() => string)' are callable. Type 'string' has no call signatures. **

like image 579
Amit Nagar Avatar asked Jul 09 '20 20:07

Amit Nagar


People also ask

Does TS have a no call signature?

The "This expression is not callable. Type 'X' has no call signatures" TypeScript error occurs when we try to call a type that isn't a function, or is typed as something else, as a function. To solve the error, make sure you're calling a function and it is typed as a function.

What is a call signature in TypeScript?

In TypeScript we can express its type as: ( a : number , b : number ) => number. This is TypeScript's syntax for a function's type, or call signature (also called a type signature). You'll notice it looks remarkably similar to an arrow function—this is intentional!


1 Answers

By saying testObj: ExampleType, you are saying that testObj will be an object in which the properties are either string or () => string. That's a broad, weak promise. However, you know exactly which properties will be of which kind.

Solution one

Tell the compiler everything you know. Include concrete property names in ExampleType.

interface ExampleType {
  firstName: string;
  lastName: string;
  gender: string;
  getFullName: () => string;
}

const testObj: ExampleType = {
  firstName: "Peter",
  lastName: "Parker",
  gender: "male",
  getFullName: () => "I am Peter Parker",
};

const { firstName, lastName, getFullName } = testObj;

console.log(getFullName()); // this works

Solution two

If you want to use ExampleType as a blueprint, but want the specific properties inferred for you, use a helper function like specific defined below.

interface ExampleType {
  [key: string]: string | (() => string);
}

const specific = <T>() => <U extends T>(argument: U) => argument;

const testObj = specific<ExampleType>()({
  firstName: "Peter",
  lastName: "Parker",
  gender: "male",
  getFullName: () => "I am Peter Parker",
});

const { firstName, lastName, getFullName } = testObj;

console.log(getFullName()); // this works
like image 112
Karol Majewski Avatar answered Jun 02 '23 06:06

Karol Majewski