在React中,Component definition看起来像这样:
class Component<S> {
state:S;
setState(state:S):void;
}
你定义一个这样的组件:
interface MyState {
name: string;
age: number;
}
class MyComponent extends Component<MyState> { }
现在我遇到的问题是,在React API setState
中应该使用部分状态对象调用,表示要更新的属性,如下所示:
setState({name: "Aaron"});
请注意,age
未声明。我遇到的问题是TypeScript不允许这样做,它会给出类似Property 'age' is missing
的赋值错误。根据我的理解,react.d.ts
定义在这个意义上是错误的。但是有解决方案吗?
我试过了:
setState({name: "Aaron"} as MyState);
但是这会产生相同的错误,即使它works in the Playground没有给出错误。为什么它在游乐场有效?有什么想法吗?
答案 0 :(得分:11)
&#34;部分类型&#34;目前仍在TypeScript中缺失,请参阅TypeScript issue #4889以及this related question。我担心它还不能正确地进行这种类型的检查。
您可能会将 MyState
界面的所有字段标记为可选(通过添加?
修饰符),但反过来削弱Component.state
之类型的类型检查(你想要设置所有字段的地方)。
编辑(2016年12月): TypeScript 2.1引入了mapped types,它支持使用Partial<T>
来描述partial types!现在,您可以对Component
使用以下类型定义:
class Component<S> {
state: S;
setState(state: Partial<S>) : void;
}
答案 1 :(得分:4)
react.d.ts
定义确实是错误的,并且在支持Partial Types之前无法修复。
问题是setState
采用部分状态,这是与正常状态不同的类型。您可以通过手动指定两种类型来解决此问题:
interface MyState {
name: string;
age: number;
}
interface PartialMyState {
name?: string;
age?: number;
}
在不延长提供的React MyComponent
类的情况下手动声明Component
:
class MyComponent {
state: MyState;
setState(state:PartialMyState): void;
//...
}
这意味着您必须为代码中的Component
的每个子类复制这些函数定义。您可以通过定义由其他类型的部分状态推广的正确Component
类来避免这种情况:
class CorrectComponent<S,P> { // generalized over both state and partial state
state:S;
setState(state:P):void;
//...
}
class MyComponent extends CorrectComponent<MyState,PartialMyState> { }
您仍然需要为您拥有的每种州类型编写部分版本。
或者,您可以通过将其参数的类型更改为setState
来使Object
非类型安全。