I have some problems with typescript when using setter & Partial
Please help me
type Options = {
param1: number;
param2: number;
}
class MyClass {
private _options: Options;
get options(): Options {
return this._options;
}
set options(newOptions: Partial<Options>) {
this._options = {
param1: newOptions?.param1 || 0,
param2: newOptions?.param2 || 0,
}
}
constructor(newOptions?: Partial<Options>) {
// Type 'Partial<Options>' cannot be assigned to type 'Options'
this._options = newOptions || {};
}
}
Throw error:
Type 'Partial' cannot be assigned to type 'Options'
CodePudding user response:
You can define a default value for the options, then overwrite all properties that are actually provided as arguments to your methods:
type Options = Record<'param1' | 'param2', number>;
const defaultOptions: Options = { param1: 0, param2: 0 };
class MyClass {
private _options: Options;
get options(): Options {
return {...this._options};
}
set options(newOptions: Partial<Options>) {
this._options = {...defaultOptions, ...newOptions};
}
constructor(newOptions?: Partial<Options>) {
this._options = {...defaultOptions, ...newOptions};
}
}
// Example:
const c = new MyClass();
console.log(c.options); // { param1: 0, param2: 0 }
c.options = {param1: 2};
console.log(c.options); // { param1: 2, param2: 0 }
c.options = {param2: 1};
console.log(c.options); // { param1: 0, param2: 1 }
Compiled JS from the TS playground:
"use strict";
const defaultOptions = { param1: 0, param2: 0 };
class MyClass {
constructor(newOptions) {
this._options = { ...defaultOptions, ...newOptions };
}
get options() {
return { ...this._options };
}
set options(newOptions) {
this._options = { ...defaultOptions, ...newOptions };
}
}
// Example:
const c = new MyClass();
console.log(c.options); // { param1: 0, param2: 0 }
c.options = { param1: 2 };
console.log(c.options); // { param1: 2, param2: 0 }
c.options = { param2: 1 };
console.log(c.options); // { param1: 0, param2: 1 }
CodePudding user response:
Consideration
Since we want to be able to set a type
Patial<Options>
(narrow) to a typeOptions
(wider)
Of many ways and without having to do any design consideration, how about any of the following:-
Candidate 1. Make the properties optional in
type Options
which as of now are mandatory.
type Options = {
param1?: number; // <--- Optional Property
param2?: number; // <--- Optional Property
}
class MyClass {
private _options: Options;
get options(): Options {
return this._options;
}
set options(newOptions: Partial<Options>) {
this._options = {
param1: newOptions?.param1 || 0,
param2: newOptions?.param2 || 0,
}
}
constructor(newOptions?: Partial<Options>) {
this._options = newOptions || {};
}
}
Candidate 2. Change the type of
option
property on the class toPartial<Options>
.
type Options = {
param1: number;
param2: number;
}
class MyClass {
private _options: Partial<Options>; // <--- The instance member itself is of type Partial<Options>
get options(): Partial<Options> { //<<--- This Partial<Options> is reflected on the interface of the class
return this._options;
}
set options(newOptions: Partial<Options>) {
this._options = {
param1: newOptions?.param1 || 0,
param2: newOptions?.param2 || 0,
}
}
constructor(newOptions?: Partial<Options>) {
this._options = newOptions || {};
}
}