【问题标题】:In typescript how to restrict the list of properties passed to a function as a parameter?在打字稿中如何限制作为参数传递给函数的属性列表?
【发布时间】:2022-12-18 20:32:47
【问题描述】:

我有这个:

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”和“nodeEditable”等问题。

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

【问题讨论】:

  • 不相关,但在新代码中我会使用for-of而不是forEach:for (const child of node.children) { /*...*/ }
  • @T.J.Crowder 完成

标签: typescript typescript-generics


【解决方案1】:

您可以通过拥有一个映射类型来做到这一点,该映射类型将仅返回可分配给给定类型的属性的类型(在您的情况下,boolean):

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

[Key in ____] 中的 as 子句省略了无法分配给目标属性类型的属性的键(通过使用 never)。例如,PropertiesOfType&lt;RegionNode, boolean&gt; 给了我们这个类型:

{
    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);
    });
}

Playground link

【讨论】:

    猜你喜欢
    • 2021-05-24
    • 2021-11-27
    • 1970-01-01
    • 2018-04-02
    • 1970-01-01
    • 1970-01-01
    • 2017-06-04
    • 1970-01-01
    • 2021-07-17
    相关资源
    最近更新 更多