7
votes
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. **

1

1 Answers

6
votes

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