Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you use spread operator to overwrite properties in typescript

Tags:

typescript

Consider this example

interface additonalProperties {
  backgroundColor: string,
  color: string,
  [key: string]: string
}

class StyleObjectMaker implements StyleObjectMaker {
  constructor(className: string, additonalProperties: additonalProperties = {}) {
    this.key = `button`
    this.className = `button${className ? '-' + className : ''}`
    this.property = {
      backgroundColor: colors[className] || colors.default,
      color: colors.default,
      ...additonalProperties
    }
  }
}

In the above ts is complaining about

'backgroundColor' is specified more than once, so this usage will be overwritten

And same for

  color

Any idea how I can fix it? i.e how can I allow to overwrite

This is how my tsconfig looks

{
  "compilerOptions": {
    "module": "commonjs",
    "noImplicitReturns": true,
    "noUnusedLocals": true,
    "outDir": "dist/ts-out",
    "sourceMap": true,
    "strict": true,
    "target": "es2017",
    "resolveJsonModule": true,
    "typeRoots": ["./node_modules/@types"]
  },
  "compileOnSave": true,
  "include": ["src", "index.ts"]
}
like image 922
iRohitBhatia Avatar asked Feb 20 '26 22:02

iRohitBhatia


2 Answers

Typescript is pointing out that these two lines are useless:

  backgroundColor: colors[className] || colors.default,
  color: colors.default,

You're setting these properties manually, but then you immediately spread over them, wiping them out. This is probably not what you meant to do. If you want these two values to trump what's found in additionalProperties, then switch the order:

this.property = {
  ...additonalProperties
  backgroundColor: colors[className] || colors.default,
  color: colors.default,
}

If the order is correct, but additionalProperties won't always have color and backgroundColor, then mark those as optional:

interface additonalProperties {
  backgroundColor?: string,
  color?: string,
  [key: string]: string
}

Or if it's behaving the way you want (ie, the properties are always getting overwritten, and that's intentional), then delete the useless lines of code.

like image 148
Nicholas Tower Avatar answered Feb 23 '26 01:02

Nicholas Tower


I had some defaults set like this that weren't a problem until Typescript 4.4 (possibly an earlier version):

Fails

    const formsValue = { 

        stateOrProvince: null, 
        stateCd: null, 
        address3: null, 
        phone: null, 

        ...addressFields 
    };

Shows error: Error TS2783: 'stateOrProvince' is specified more than once, so this usage will be overwritten. which makes sense.

The destination for this value is an Angular form which requires empty fields to be explicitly set. While normally addressFields would contain a value for every field (as specified by its type) I had some older customers who may have a cached value in their local storage without all these fields hence these defaults.

Fortunately the following seems to get around the error, and I think looks nicer anyway as it groups things together.

Works

    const formsValue = { 

        ...{
            stateOrProvince: null, 
            stateCd: null, 
            address3: null, 
            phone: null, 
        },

        ...addressFields 
    };

Not 100% sure why the compiler lets this through but it does :-)

like image 21
Simon_Weaver Avatar answered Feb 23 '26 02:02

Simon_Weaver