Reputation: 11900
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"]
}
Upvotes: 13
Views: 17029
Reputation: 146140
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 :-)
Upvotes: 4
Reputation: 2555
Typescript's Partial
utility type seems the best way to make this happen.
In your example, the constructor would be changed to:
constructor(className: string, additonalProperties: Partial<additonalProperties> = {})
Upvotes: 3
Reputation: 914
I don't know if there is a configuration for this. However, you could destructure additionalProperties
to exclude color
and backgroundColor
:
class StyleObjectMaker implements StyleObjectMaker {
constructor(className: string, additonalProperties: additonalProperties = {}) {
const { backgroundColor, color, ...rest } = additionalProperties;
this.key = `button`
this.className = `button${className ? '-' + className : ''}`
this.property = {
backgroundColor: colors[className] || colors.default,
color: colors.default,
...rest
}
}
}
If you want those props to be just default values, you can make use of Object.assign.
class StyleObjectMaker implements StyleObjectMaker {
constructor(className: string, additonalProperties: additonalProperties = {}) {
const finalProperties = Object.assign({}, {
backgroundColor: colors[className] || colors.default,
color: colors.default,
}, additionalProperties);
this.key = `button`
this.className = `button${className ? '-' + className : ''}`
this.property = finalProperties;
}
}
Upvotes: 1
Reputation: 85122
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.
Upvotes: 16