我有不同类型的视图,这些视图在它们具有的属性和可以更改的属性方面有所不同。我尝试创建一个updateView函数,该函数将视图和一些更改传入,合并,然后在后端更新视图。该函数应根据传入的视图类型限制传入的更改,但这不能正常工作。我在下面发布了一个示例。
如何更改UpdateView接口以适当限制可以传入的更改?
interface BaseView {
immutableProp?: string;
mutableProp?: string;
name: string;
isCustom: boolean;
}
interface StandardView extends BaseView {
isCustom: false;
}
interface CustomView extends BaseView {
isCustom: true;
}
type View = StandardView | CustomView
type StandardMutableFields = Partial<Pick<StandardView, "mutableProp">>
type CustomMutableFields = Partial<Pick<CustomView, "mutableProp" | "name">>
interface UpdateView {
<T extends View>(viewToChange: T, changes: T extends CustomView ? CustomMutableFields : StandardMutableFields): T
}
const updateView: UpdateView = (viewToChange, changes) => {
const updatedView = { ...viewToChange, changes };
// SAVE TO SERVER
return updatedView;
}
const changeName = (view: View, name: string) => {
updateView(view, { name: "this is allowed but shouldn't be" }) // should require a check to ensure the view is custom
}
答案 0 :(得分:1)
我认为这里最简单的解决方案(至少从我在问题中看到的)是删除条件类型和泛型函数,而只是使用重载。
本质上无法使用可能的参数类型的并集来调用重载,因此该调用可以使用CustomView
或StandardView
进行调用,但不能使用两者的并集进行调用,因此自然会迫使您区别对待在执行通话之前,两者之间:
interface UpdateView {
(viewToChange: CustomView, changes: CustomMutableFields): CustomView
(viewToChange: StandardView, changes: StandardMutableFields): StandardView
}
const updateView: UpdateView = (viewToChange: CustomView | StandardView, changes : CustomMutableFields | StandardMutableFields) => {
const updatedView = { ...viewToChange, changes };
// SAVE TO SERVER
return updatedView as any;
}
const changeName = (view: View, name: string) => {
updateView(view, { name: "this is allowed but shouldn't be" }) // err
if (view.isCustom) {
updateView(view, { name: "this is allowed but shouldn't be" }) // ok
}
}