Aaron Aaron - 1 month ago 10x
React JSX Question

TypeScript partial interface object

In React, the Component definition looks something like this:

class Component<S> {

And you define a component like this:

interface MyState {
name: string;
age: number;
class MyComponent extends Component<MyState> { }

Now the issue I have is that in the React API
is supposed to be called with a partial state object, representing properties to be updated, like this:

setState({name: "Aaron"});

Note that
is not declared. The problem I have is that TypeScript doesn't allow this, it gives an assignment error like
Property 'age' is missing
. By my understanding, the
definition is wrong in this sense. But is there a solution?

I tried this:

setState({name: "Aaron"} as MyState);

But this gives the same error, even though it works in the Playground without giving an error. Why does it work in the Playground? Any ideas?


The react.d.ts definition is indeed wrong, and cannot be fixed until Partial Types are supported.

The problem is that setState takes a partial state, which is a different type from normal state. You can solve this by manually specifying both types:

interface MyState {
    name: string;
    age: number;

interface PartialMyState {
    name?: string;
    age?: number;

And manually declaring MyComponent without extending the provided React Component class:

class MyComponent {
    state: MyState;
    setState(state:PartialMyState): void;

Which means you'll have to duplicate these function definitions for every subclass of Component in your code. You may be able to avoid this by defining a correct Component class generalized by an additional type of partial state:

class CorrectComponent<S,P> { // generalized over both state and partial state

class MyComponent extends CorrectComponent<MyState,PartialMyState> { }

You'll still have to write a partial version for every state type you have.

Alternatively, you can make setState non-typesafe by changing its argument's type to Object.