【问题标题】:How to apply the interface according to the object property value如何根据对象属性值应用接口
【发布时间】:2022-01-09 05:10:43
【问题描述】:

I wrote it again by summarizing the contents of the article.

我想知道如何根据对象属性值应用接口。

我在下面写了一个简单的示例代码。

一共有三个节点:root、dept、user。

指定每个节点对应的类型。因此,我们希望根据对象类型属性来指定接口。

但是,您可以看到您正在手动确认类型,因为您还没有找到解决方案。

为了解决这个问题,我认为应该用索引类型而不是条件类型来解决。

原因是条件类型期望根据泛型类型参数计算返回,但当前问题应该是根据现有类型计算而不是接收类型参数。

但是,即使使用两种方法也无法解决问题。任何帮助将不胜感激??????♂️

export enum NodeType {
  root = "root",
  dept = "dept",
  user = "user",
}

interface Node {
  readonly type: NodeType;
  title: string;
}

interface RootNode extends Node {
  type: NodeType.root;
}

interface DeptNode extends Node {
  type: NodeType.dept;
  departmentCode: string;
}

interface UserNode extends Node {
  type: NodeType.user;
  employeeNumber: string;
}

const nodeData: Node[] = [
  {
    type: NodeType.root,
    title: "Company 1",
  } as RootNode,
  {
    type: NodeType.dept,
    title: "Department 1",
    departmentCode: "557",
    // The type is not inferred according to the object property type, so the type must be explicitly asserted.
  } as DeptNode,
  {
    type: NodeType.user,
    title: "User 1",
    employeeNumber: "201911",
  } as UserNode,
];

// I want to be the type of DeptNode interface because the type of object property is NodeType.dept.
const selectDept = nodeData.filter((x) => x.type === NodeType.dept);
selectDept.forEach((x) => {
  console.log({
    type: x.type,
    title: x.title,
    // The type is not affirmed in the node that fits the object property type, so you have to affirm the type yourself.
    departmentCode: (x as DeptNode).departmentCode,
  });
});

【问题讨论】:

    标签: typescript types conditional-types typescript-types


    【解决方案1】:

    我知道如何使用types,而不是interfaces。

    您的尝试有两个问题:

    1. 通过使用类型,您可以利用discriminated unions (注意 Node 类型是三种可能情况的并集)。
    2. 对于filterforEach等数组方法,推断 算法不够聪明,无法理解请求的内容 类型,因此您必须使用简单的forif。在这里阅读更多:https://stackoverflow.com/a/62033938/632445

    我们开始吧:

    export enum NodeType {
        root = "root",
        dept = "dept",
        user = "user",
    }
    
    type NodeBase = {
        readonly type: NodeType;
        title: string;
    }
    
    type RootNode = NodeBase & {
        type: NodeType.root;
    }
    
    type DeptNode = NodeBase & {
        type: NodeType.dept;
        departmentCode: string;
    }
    
    type UserNode = NodeBase & {
        type: NodeType.user;
        employeeNumber: string;
    }
    
    type Node = RootNode | DeptNode | UserNode;
    
    const nodeData: Node[] = [
        {
            type: NodeType.root,
            title: "Company 1",
        },
        {
            type: NodeType.dept,
            title: "Department 1",
            departmentCode: "557",
            // The type is not inferred according to the object property type, so the type must be explicitly asserted.
        },
        {
            type: NodeType.user,
            title: "User 1",
            employeeNumber: "201911",
        },
    ];
    
    // I want to be the type of DeptNode interface because the type of object property is NodeType.dept.
    for (const x of nodeData) {
        if (x.type === NodeType.dept) {
            console.log({
                type: x.type,
                title: x.title,
                // The type is not affirmed in the node that fits the object property type, so you have to affirm the type yourself.
                departmentCode: (x as DeptNode).departmentCode,
            });
        }
    }
    

    【讨论】:

    • 感谢您的回答。额外的测试证实,即使它被定义为接口,它的工作方式也与 Intersection Type 相同。因此,将其用作接口似乎没有问题。
    • TypeScript 中的类型和接口几乎是一回事。对我来说,除了语法之外,还不清楚有什么区别。我倾向于在任何地方使用类型,但这只是我的编码选择。更多信息:stackoverflow.com/questions/37233735/…
    猜你喜欢
    • 2018-10-17
    • 2019-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-30
    • 2018-04-07
    • 2021-11-03
    • 2015-08-31
    相关资源
    最近更新 更多