I have a component class that extends another component, and I'm trying to figure out how to overwrite the type of the state that I'm inheriting from.
Here's an example:
class MyComponent extends React.Component<SomeProps, SomeState> {
// ...
}
class ExtendedComponent extends MyComponent {
// How to overwrite SomeState?
// This component needs to store a different model of state.
}
I need ExtendedComponent
to use a different interface
for its state
, but I can't quite figure out how to accomplish this.
EDIT: Getting somewhere now!
However, now Parent
is getting stuffed with all kinds of errors pertaining to state modifications. Here's what I've got so far:
interface ParentProps {
a: string;
}
interface ParentState {
b: string;
}
class Parent<P, S> extends React.Component<ParentProps & P, ParentState & S> {
constructor(props) {
super(props);
// Type '{ b: "hello"; }' is not assignable to type 'Readonly<ParentState & S>'
this.state = {
b: 'hello',
};
}
aFunction(): void {
/*
Argument of type '{ b: "testing"; }' is not assignable to parameter of type '(ParentState & S) | ((prevState: Readonly<ParentState & S>, props: Readonly<ParentProps & P>) => (ParentState & S) | Pick<ParentState & S, "b">) | Pick<ParentState & S, "b">'.
Type '{ b: "testing"; }' is not assignable to type 'Pick<ParentState & S, "b">'.
Types of property 'b' are incompatible.
Type '"testing"' is not assignable to type 'string & S["b"]'.
Type '"testing"' is not assignable to type 'S["b"]'.
*/
this.setState({
b: 'testing',
});
}
}
interface ChildProps {
c: string;
}
interface ChildState {
d: string;
}
class Child extends Parent<ChildProps, ChildState> {
constructor(props) {
super(props);
// This is what I'm after -- and TypeScript doesn't complain :)
this.state = {
b: 'hello',
d: 'world',
};
}
}
EDIT 2:
Extending another component class is not recommended by the maintainers of React. This is for good reason, as I had to maintain this approach in a production application which was abysmal! I ended up re-writing a lot of code using higher-order components and custom hooks.
There's a reason that this use-case isn't very supported, avoid creating complication caused by over-engineering your components! Imagine trying to explain your tangled mess of inheritance to another developer.
Just because it sounds cool and you can do it, doesn't mean you should. I highly recommend using functional components, and if you need shared functionality, use higher-order functions, and/or custom hooks.
I'm guessing you don't want to replace the props and state, because you probably need a common interface to make the parent class work. So you could make your parent class generic, and then merge in the additional pieces of props/state.
class MyComponent<P, S> extends React.Component<ParentProps & P, ParentState & S> {}
// ^ Generic P is for child props, Generic S is for child state
Example in use:
type ParentProps = { a: number }
type ParentState = { b: number }
class MyComponent<P, S> extends React.Component<ParentProps & P, ParentState & S> {}
let parentComponent = <MyComponent a={1} />
type ChildProps = { c: number }
type ChildState = { d: number }
class ExtendedComponent extends MyComponent<ChildProps, ChildState> {}
let childComponent = <ExtendedComponent a={1} c={2} />
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