Joj*_*oji 12 typescript reactjs
首先,您将看到的代码片段是一个人为的示例。我只是好奇为什么打字不起作用。
interface MyState {
a: boolean;
b: number;
}
const defaultState: MyState = {
a: false,
b: 1
};
const keys = Object.keys(defaultState) as Array<keyof MyState>;
export default function App() {
const [myState, setMyState] = React.useState<MyState>(defaultState);
React.useEffect(() => {
keys.forEach((key) => {
setMyState((prev) => ({
...prev,
[key]: "lol". // should've given an error but it didn't
}));
});
}, []);
Run Code Online (Sandbox Code Playgroud)
所以我有一个defaultState
和它在组件外部定义的键列表。在 useEffect 中,我使用密钥来更新状态(现在它只是将每个值更改为“lol”)。我传递了一个回调作为 中的更新程序,setMyState
它返回的应该是新状态。但是在这里我将值设为字符串,这违反了我拥有的接口MyState
。
我想知道为什么它没有触发错误
这是一个现场演示:https : //codesandbox.io/s/sweet-dewdney-u83id?file=/ src/ App.tsx
没有反应的最小例子:游乐场
问题不在于使用回调来更新状态 - 这很好。问题是,当您使用动态键设置对象的属性时,打字稿不知道循环的任何给定迭代的键值是什么,更不用说它的值应该是什么类型了。所以你需要告诉它。您需要使用泛型动态键入密钥。这里有一篇关于它的很棒的文章。
function updateValue<T extends keyof MyState, K extends MyState[T]>(
name: T,
value: K
) {
setMyState(prev => ({ ...prev, [name]: value }));
}
React.useEffect(() => {
keys.forEach((key) => {
updateValue(key, "lol");
});
}, []);
Run Code Online (Sandbox Code Playgroud)
完全按照应有的方式给出错误。
这有一些有趣的怪癖。如果将该值设置为界面上可能的值之一会怎样?
keys.forEach((key) => {
updateValue(key, 4); // <---- no error, but there should be
});
Run Code Online (Sandbox Code Playgroud)
理论上,这也应该引发错误,因为key
可能是a
,在这种情况下类型不匹配。TypeScript 不会抛出错误。但是,如果您指定仅在 时运行此命令key === 'a'
,则会出现错误:
keys.forEach((key) => {
if (key === 'a'){
updateValue(key, 4); // <---- typechecking error occurs
}
});
Run Code Online (Sandbox Code Playgroud)
在后一种情况下,打字稿足够聪明,知道如果键是a
,则类型必须是数字。但在前一种情况下,当您尝试分配一个与接口上的一种类型(但不是所有类型)匹配的值时,我们可能会看到错误,或者达到打字稿的限制。
归档时间: |
|
查看次数: |
209 次 |
最近记录: |