Given
class A {
props: {
bool?: boolean,
test: string
} = {
test: 'a'
};
setProps(newProps: Partial<this['props']>) {
}
a() {
this.setProps({
bool: false
});
}
}
I get an error
Argument of type
{ bool: false; }
is not assignable to parameter of typePartial<this["props"]>
.(2345)
As can be viewed here: same code in typescript playground
When the A.props
property is defined as {bool?: boolean, test?: string}
with test
optional it does work, so it looks as if the Partial<>
is just completely ignored.
Is there a way to get the Partial
to work in conjunction with this
.
The above describes the minimal case, for context: My current situation is that I have lots of classes with props that extends from a main class that has a setProps
and I would like to type that inherited setProps
.
class Parent {
props: any;
setProps(newProps: Partial<this['props']>) {/*...*/}
}
class A extends Parent{
props: {
bool?: boolean,
test: string
} = /* ... */;
a() {
this.setProps({
bool: false
});
}
}
Edit #2: Maybe another approach is more suitable for you. The following code implements the class Parent
as an generic one receiving the interface of the properties (here PropsA
) of an extending class (here A
).
class Parent<T> {
props: T;
constructor(props: T) {
this.props = props;
}
setProps(props: Partial<T>) {
Object.assign(this.props, props);
}
}
interface PropsA {
bool?: boolean;
test: string;
}
class A extends Parent<PropsA> {
constructor() {
super({ test: 'A' });
}
a() {
this.setProps({
bool: false,
// Yields error:
// nonExistingProperty: true
});
}
}
const obj = new A();
console.log(obj.props); // { test: 'a' }
obj.setProps({ test: 'foo', bool: true });
console.log(obj.props); // { test: 'foo', bool: true }
obj.setProps({ test: 'foo' });
console.log(obj.props); // { test: 'foo', bool: true }
obj.a();
console.log(obj.props); // { test: 'foo', bool: false }
// Yields error:
// obj.setProps({ test: 'foo', nonExistingProperty: true });
Instead of an interface, something like class A extends Parent<{ bool?: boolean; test: string;}> { ...
would also do the job. However I think, that an interface makes more sense here.
Edit #1: I have experimented a bit with ThisType
. However I am not sure about its benefit, but maybe it is worth to mention:
type Descriptor<T, P> = ThisType<T> & Partial<P>;
class A {
props: {
bool?: boolean,
test: string
} = {
test: 'a'
};
setProps<T = Descriptor<this, this['props']>>(newProps: T) {
Object.assign(this.props, newProps);
}
a() {
this.setProps({
bool: true
});
}
}
const obj = new A();
console.log(obj.props); // { test: 'a' }
obj.setProps({ test: 'foo', bool: true });
console.log(obj.props); // { test: 'foo', bool: true }
Original answer: Try Partial<A['props']>
:
class A {
props: {
bool?: boolean,
test: string
} = {
test: 'a'
};
setProps(newProps: Partial<A['props']>) {
// First naive assignment
Object.assign(this.props, newProps);
}
a() {
this.setProps({
bool: false
});
}
}
I guess the error appears because of this
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With