Frances
Frances

Reputation: 29

Use a type as a function Typescript

I have a Type here to convert an ID to an object, I understand this allows personId as a string parameter and returns a Person/undefined.

export type FindPerson = (personId: string) => Person | undefined;

I have bunch of person IDs and would like to use this type to convert to Person objects. I tried this way but it didnt work, it returns a FindPerson object instead a Person object.

const person = { personId: "1923-01-01a" } as unknown as FindPerson;

Is there any way that I can re-use the type above to get a Person object by ID?

Upvotes: 1

Views: 150

Answers (1)

T.J. Crowder
T.J. Crowder

Reputation: 1074295

The type you have just defines the type of a function. It doesn't define any code for an actual function. You can't use it to convert a string to a Person | undefined because it doesn't actually do anything, it just defines the type of something that would do something if you created one. Types don't exist at runtime (other than enums, which have some runtime presence). A type can't convert a value. (Types can convert types, but not values.)

You'll need to write a function that does the work of accepting a string and returning either a Person or undefined. For instance:

const findPerson: FindPerson = (personId: string) => {
    // ...code to do the work...
};

Here's an example with context, though of course most of this is stand-in code for what your real code would be:

// Placeholder
type Person = {
    id: string;
    name: string;
}

// Your type
/*export*/ type FindPerson = (personId: string) => Person | undefined;

// Stand-in for the actual person storage
const personStore: Map<string, Person> = new Map();
function addPerson(id: string, name: string) {
    personStore.set(id, {id, name});
}
addPerson("1923-01-01a", "Joe Bloggs");
addPerson("1924-01-01b", "Mohammed bin Ammar");
addPerson("1925-01-01c", "Constanza Alvares");

// The function
const findPerson: FindPerson = (personId: string) => {
    return personStore.get(personId);
};

// Using it
const person = findPerson("1923-01-01a");
console.log(person);
console.log(findPerson("1924-01-01b"));
console.log(findPerson("no-such-person"));

Playground link

A type like your FindPerson is mostly useful when:

  1. You want to defend against coding errors during maintenance, such as someone adding a parameter or changing the function so that it doesn't return the correct value. (Particularly useful with several functions presenting the same interface.)

  2. You'll already have a function but the parameter names aren't as clear as they would be if you renamed them. For instance, in the above, we could have defined findPerson like this:

    const findPerson: FindPerson = personStore.get.bind(personStore);
    

    Without the type annotation, the hint for the parameter would be key (inherited from the type of Map.prototype.get). But with the type annotation, it's the more-specific personId.

Upvotes: 2

Related Questions