Search code examples
typescriptoption-type

How should I create an object, copying optional properties only if they exist?


I'm writing code that maps objects between different domains. Often times, the objects have multiple optional fields, and I want to copy them if they exist. My attempts in the code below:

  • createFrom1: works, but has a lot of repetition.
  • createFrom2: Doesn't work - optional properties become undefined

How can I accomplish this?

TypeScript playground link

interface type1 {
    mandatoryX: string; // plus more...
    optionalFoo?: string;
    optionalBaz?: string
}

interface type2 {
    mandatoryY: string; // plus more...
    optionalBar?: string;
    optionalBaz?: string
}

function createFrom(input: type1) : type2 {
    const output : type2 = {
        mandatoryY: input.mandatoryX,
    };

    if (input.optionalFoo != null) {
        output.optionalBar = input.optionalFoo;
    }

    if (input.optionalBaz != null) {
        output.optionalBar = input.optionalBaz;
    }

    return output;
}

function createFrom2(input: type1) : type2 {
    return {
        mandatoryY: input.mandatoryX,
        optionalBar: input.optionalFoo, // Doesn't work right - if input.optionalFoo is not defined, will create optionalBar: undefined
        optionalBaz: input.optionalBaz,
    };
}

Solution

  • You can achieve this by using Spread syntax:

    function createFrom2(input: type1) : type2 {
        return {
            mandatoryY: input.mandatoryX,
            ...input.optionalFoo && { optionalBar: input.optionalFoo }, 
            ...input.optionalBaz && { optionalBaz: input.optionalBaz },
        };
    }
    

    Playground