在我的 React 应用程序中,我使用 Unstated 来管理共享状态,但是我在 TypeScript 中使用时遇到了问题:<Subscribe>
组件向我传递了一个键入为Container<any>
的状态实例。这意味着它需要转换为我自己的类型,例如Container<MyState>
,在我安全使用它之前。
相反,如果我希望 Unstated 向我传递容器的已类型实例,我应该如何包装和/或分叉 Unstated 源和/或其类型文件,以便在我获得Container
实例时,它被类型化为Container<MyState>
?
顺便说一句,我想获得传入类型容器的特殊原因是,我可以使用复杂状态的解构,而不必切换到使用更冗长的胖箭头函数的块形式。
下面是我希望能够编写的代码的简化示例:
function Counter() {
return (
<Subscribe to={[CounterContainer]}>
{({increment, decrement, state}) => (
<div>
<button onClick={() => decrement()}>-</button>
<span>{state.count}</span>
<button onClick={() => increment()}>+</button>
</div>
)}
</Subscribe>
);
}
这是我目前编写它的方式,在一个使用 TypeScript 的简化的 Unstated 示例中:
import React from 'react';
import { render } from 'react-dom';
import { Provider, Subscribe, Container } from 'unstated';
interface CounterState {
count: number
};
class CounterContainer extends Container<CounterState> {
public state = {
count: 0
};
public increment() {
this.setState({ count: this.state.count + 1 });
}
public decrement() {
this.setState({ count: this.state.count - 1 });
}
}
function Counter() {
return (
<Subscribe to={[CounterContainer]}>
{(counter: CounterContainer) => {
const {increment, decrement, state} = counter;
return (
<div>
<button onClick={() => increment()}>-</button>
<span>{state.count}</span>
<button onClick={() => decrement()}>+</button>
</div>
)
}}
</Subscribe>
);
}
render(
<Provider>
<Counter />
</Provider>,
document.getElementById('root')
);
因此,查看最初添加打字稿定义的 PR,请注意,他们找不到自动提供您正在寻找的类型的方法,因为像 $TupleMap 这样的东西在 TS 中不存在,就像它在 Flow 中一样,您必须手动提供键入。
如果您的主要动机是避免使用箭头函数使用额外的 {},您可以手动提供键入并仍然执行相同的解构。所以从你的例子中:
function Counter() {
return (
<Subscribe to={[CounterContainer]}>
{({increment, decrement, state}: CounterContainer) => (
<div>
<button onClick={() => increment()}>-</button>
<span>{state.count}</span>
<button onClick={() => decrement()}>+</button>
</div>
)
}
</Subscribe>
);
}
也有效。也许有一种方法可以在 Typescript 中自动键入它,但它超出了我的范围。