Two similar types – how to make function for them?

How can I create a function that takes two similar types and at the same time returns them?

My example:

   type First = {
        name: string,
        address: string,  
    }
    
    type Second = {
        name: string,
        email: string,
    }
    
    type Third = First | Second;
    
    function addSuffix(payload: Third): Third {
        payload.name += "suffix";
        return payload;
    }
    
    const a: First = {
        "name": "John",
        "address": "London",
    }
    
    const b: Second = {
        "name": "Alice",
        "email": "alice@alice.com"
    }
    
    function doA(payload: First): First {
        // some operations
        return addSuffix(payload);
    }
    
    function doB(payload: Second): Second {
        // some operations
        return addSuffix(payload);
    }
    
    doA(a);
    doB(b);

It’s not working because of:

Type ‘Third’ is not assignable to type ‘First’. Property ‘address’ is
missing in type ‘Second’ but required in type ‘First’.

How can I change the addSuffix function to make it work? In other OOP language programming, I would use interfaces (interface with name property), but how to do it in TypeScript?

>Solution :

The issue is that the function signature of addSuffix doesn’t express the fact that it will always return the same type you pass in. This means that doA and doB can’t be sure that it will return the type they’re expecting.

In other OOP language programming I would use interfaces (interface with name property), but how to do it in TypeScript?

Luckily, TypeScript also has interfaces:

interface Nameable {
    name: string;
}

function addSuffix<T extends Nameable>(payload: T): T {
    payload.name += "suffix";
    return payload;
}

You don’t have to manually implement Nameable for First and Second, as it is implied by the fact they both have name fields.

It’s also worth noting that you can also use a type alias instead of an interface to achieve the same thing, just with slightly different syntax:

type Nameable = {
    name: string
}

function addSuffix<T extends Nameable>(payload: T): T {
    payload.name += "suffix";
    return payload;
}

Or you can even inline it:

function addSuffix<T extends { name: string }>(payload: T): T {
    payload.name += "suffix";
    return payload;
}

Leave a Reply