TypeScript部分接口对象

时间:2016-04-14 20:45:01

标签: reactjs typescript

在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没有给出错误。为什么它在游乐场有效?有什么想法吗?

2 个答案:

答案 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非类型安全。