volna
volna

Reputation: 2610

How to add properties to initially typed object

The example below uses quite simple object structures (it's slightly simplified for the purpose of the question). The logic uses cloning to avoid mutating original configuration object.

I am new to TS and a bit puzzled to understand how to preserve typesafe way of coding, in order to modify object and return it typed with another type.

I will also appreciate your thought on this approach in TS and will be glad to learn about a better one :)

Here is an example of working code in codesandbox

function cloneDeep<T>(object: T): T {
  return JSON.parse(JSON.stringify(object)) as T;
}

type initialConfigType = {
  a: {
    b: number
  }
  c: number
};

interface extendedConfigType extends initialConfigType {
  d: number
}

const initalConfig: initialConfigType = {
  a: {
    b: 1
  },
  c: 1
};

function extendConfig(config: initialConfigType) {
  const configClone = cloneDeep(config)

  // Property 'd' does not exist on type 'initialConfigType' 
  configClone.d = 3

  return configClone as extendedConfigType
}

const extendedConfig = extendConfig(initalConfig)

Upvotes: 0

Views: 91

Answers (2)

koalaok
koalaok

Reputation: 5720

For deep cloning I recommend to use lodash library, which already implements a clonedeep func.

const clonedeep = require('lodash.clonedeep');

To stick to your way this should work. With no lint errors

function cloneDeep<T>(object: T): T {
    return JSON.parse(JSON.stringify(object)) as T;
}

type initialConfigType = {
    a: {
        b: number
    }
    c: number
};

interface extendedConfigType extends initialConfigType {
    d: number
}

const initalConfig: initialConfigType = {
    a: {
        b: 1
    },
    c: 1
};

function extendConfig(config: initialConfigType): extendedConfigType {
    let configClone: extendedConfigType;
    configClone = { ...configClone, ...{ config } }
    configClone.d = 3

    return configClone;
}

const extendedConfig = extendConfig(cloneDeep(initalConfig))

initalConfig.a.b = 9;

console.log(initalConfig, extendedConfig);

Upvotes: 0

Roberto Zvjerković
Roberto Zvjerković

Reputation: 10127

Maybe don't change the original config:

function extendConfig(config: initialConfigType) {
  return {
    ...cloneDeep(config),
    d: 3
  }
}

Upvotes: 1

Related Questions