在typescript如何限制属性的列表传递给一个函数作为参数?



我有这个:

export interface RegionNode {
nodeSelected: boolean;
nodeEditable: boolean;
zone: Partial<Zone>;
parent: RegionNode | null;
children: RegionNode[];
}

我想要一个泛型函数来做这个:

function setNodeAndChildrenProperty(node: RegionNode, property: keyof RegionNode, state: boolean): void {
// @ts-ignore
node[property] = state;
for (const child of node.children) {
setNodeAndChildrenProperty(child, property, state);
};
}

但是你可以看到,我不得不使用@ts-ignore,因为我不知道如何将允许的属性列表限制为"nodeSelected"one_answers";nodeEditable"等等。

解决这个问题的优雅方法是什么?

您可以通过使用映射类型来实现这一点,该类型将返回可分配给给定类型(在您的示例中为boolean)的属性的类型:

type PropertiesOfType<ObjType, PropType> = {
[Key in keyof ObjType as ObjType[Key] extends PropType ? Key : never]: ObjType[Key];
};

[Key in ____]中的as子句省略了不能分配给目标属性类型的属性的键(通过使用never)。例如,PropertiesOfType<RegionNode, boolean>给了我们这样的类型:

{
nodeSelected: boolean;
nodeEditable: boolean;
}
然后你可以在你的函数中使用它,这样TypeScript就知道node[property]的类型和state的类型是兼容的:
function setNodeAndChildrenProperty(
node: RegionNode,
property: keyof PropertiesOfType<RegionNode, boolean>, // <====
state: boolean
): void {
node[property] = state;
node.children.forEach((child) => {
setNodeAndChildrenProperty(child, property, state);
});
}

操场上联系

最新更新