Pet*_*ard 2 javascript interface instance readonly typescript
我有这个问题。
带接口:
export interface IDevice {
id: string,
selected: boolean
}
Run Code Online (Sandbox Code Playgroud)
通过以下方式创建实例:
let newDevice: IDevice = {
id: uuid4(),
selected: false,
} as IDevice;
Run Code Online (Sandbox Code Playgroud)
它以反冲状态添加到数组中,并在 React 中用于使用 useRecoilState() 检索数组的函数中。
const [leftList, setLeftList] = React.useState<IDevice[]>([]);
现在它在处理程序中用于选择列表控件上的设备,这里发生错误:
...
leftList.map((item: IDevice) => {
if (item.id === event.dataItem.id) {
item.selected = !item.selected;
}
return item;
})
...
Run Code Online (Sandbox Code Playgroud)
我收到错误:无法分配给对象“#”的只读属性“选定”
即使先通过 [...leftList] 克隆数组也没有帮助。
我迷路了:-)希望有人能对此有所了解吗?
不应直接修改状态,这就是您当前.map()通过更新对象在方法中所做的事情。TS 试图通过将对象设置为只读来告诉您不要这样做。
相反,您可以创建一个包含所有属性的新对象item(使用展开语法 ...完成),以及一个新的覆盖属性selected,如果 id 与事件的数据匹配,它将使用该项目当前所选项目的否定版本项目 id,否则它将保留原始选择的值:
leftList.map((item: IDevice) => ({
...item,
selected: item.id === event.dataItem.id ? !item.selected : item.selected
}))
Run Code Online (Sandbox Code Playgroud)
使用扩展语法([...leftList])克隆数组只会进行浅拷贝,不会对数组中的对象进行深拷贝,因此修改数组中的对象引用.map()仍然是修改原始状态。
或者,您可以只在想要修改属性时返回一个新创建的对象,而不是每次扩展对象并创建一个新对象(这可能会稍微影响性能,如@3limin4t0ritem指出的那样):selected
leftList.map((item: IDevice) => {
if (item.id !== event.dataItem.id) return item;
return {...item, selected: !item.selected};
});
Run Code Online (Sandbox Code Playgroud)