In React, the Component definition looks something like this:
class Component {
state:S;
setState(state:S):void;
}
And you
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
state:S;
setState(state:P):void;
//...
}
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
.
"Partial types" are still missing in TypeScript currently, see TypeScript issue #4889 as well as this related question. I'm afraid it's not yet possible to make this type-check correctly.
You might get away with marking all fields of your MyState
interface as optional (by adding ?
modifiers), but that in turn weakens the type-checking for things like Component.state
(where you want all fields to be set).
EDIT (December 2016): TypeScript 2.1 introduces mapped types, which supports describing partial types using Partial<T>
! Now you can use the following type definition for Component
:
class Component<S> {
state: S;
setState(state: Partial<S>) : void;
}