使用传播运算符或Object.assign将失去严格的打字稿检查。
type State = {
key1: string;
key2: string;
};
function App() {
const [state, setState] = React.useState<State>({
key1: "",
key2: ""
});
React.useEffect(() => {
setState(prevState => {
return { ...prevState, ...{ key3: "" } };//no ts error
});
setState(prevState => {
return Object.assign({}, prevState, { key3: "" });//no ts error
});
setState({key1:'', key2:'', key3: ''});//ts error!!
}, []);
return <div>{JSON.stringify(state)}</div>;
}
我尝试使用Vanilla TS,还是有问题
type Person = {
name: string,
age: number
}
const person1:Person = {...{name: 'a', age: 20, salary: 20}};//no error
const person2:Person = Object.assign({name: 'a', age: 20, salary: 20});//no error
const person3:Person = {name: 'a', age: 20, salary: 20};//ts error
似乎ts有一些错误。我想知道是否有一种使用严格类型检查来更新状态的简单方法?有人可以指导我做这个吗?
答案 0 :(得分:3)
是的,这似乎是Typescript社区中的一个已知问题。 Check this discussion on Github out
有一个解决方法。 可以参考here。
TLDR;
在合并两者以形成新状态之前,您基本上可以输入新状态。两种正确键入的状态将导致正确键入状态。
看看这个片段:
(() => {
type State = { foo: string };
const state: State = { foo: 'bar' };
const assignedValues: State = { foo: 1 }; //complain expected
const newState: State = Object.assign({}, state, assignedValues)
})();
据此,我认为您的新代码将如下所示:
const [state, setState] = React.useState<State>({
key1: "",
key2: ""
});
React.useEffect(() => {
setState(prevState => {
const valueToChange: Partial<State> = {
key1: "I am sure that this is typed",
}
return Object.assign({}, prevState, valueToChange);
});
}, []);
return <div>{JSON.stringify(state)}</div>;
答案 1 :(得分:3)
iamfeek's answer(将新状态分配给具有正确类型的变量/常量以进行类型检查,然后从该变量/常量中合并)就目前而言是正确的,但是您可能会想要将setState(prevState => {
const merge:Partial<State> = { key3: "" } }; // Flags up the error
return { ...prevState, ...merge }; // Or return Object.assign({}, prevState, merge);
});
添加到您的实际用例中。
Partial<State>
State
允许合并对象仅包含function mergeState(state:State, merge:Partial<State>) {
return { ...prevState, ...merge };
}
的属性的子集,但没有使其具有不正确的属性。
也许甚至给自己一个实用程序功能:
setState(prevState => {
return mergeState(prevState, { key3: "" } ); // Flags up the error
});
然后
{{1}}