TypeScript中如何限制函数参数允许传入的属性列表?
问题与解决方案
问题描述
定义了如下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,因为无法将传入的property参数限制为仅nodeSelected和nodeEditable这两个值为布尔类型的属性,需要优雅的解决方案。
解决方案
方案1:直接指定允许的属性字面量
直接将property的类型设为'nodeSelected' | 'nodeEditable',明确限定可传入的属性名称:
function setNodeAndChildrenProperty(node: RegionNode, property: 'nodeSelected' | 'nodeEditable', state: boolean): void { node[property] = state; for (const child of node.children) { setNodeAndChildrenProperty(child, property, state); } }
这种方式简单直接,适合属性列表固定的场景,TypeScript会自动校验传入的属性是否在允许范围内,无需忽略类型检查。
方案2:通过类型工具动态提取布尔属性键
如果需要适配RegionNode中所有值为布尔类型的属性(包括未来新增的),可以定义一个类型工具来提取对应键:
// 提取对象中值为boolean类型的属性键 type BooleanKeys<T> = { [K in keyof T]: T[K] extends boolean ? K : never }[keyof T]; function setNodeAndChildrenProperty(node: RegionNode, property: BooleanKeys<RegionNode>, state: boolean): void { node[property] = state; for (const child of node.children) { setNodeAndChildrenProperty(child, property, state); } }
这个类型工具BooleanKeys会遍历T的所有键,只保留值类型为boolean的键。当RegionNode新增布尔类型属性时,函数会自动支持该属性,无需修改函数的参数类型定义。
内容的提问来源于stack exchange,提问作者Stéphane Gerber
相关产品推荐
相关产品推荐

