如何根据对象属性值应用接口

How to apply the interface according to the object property value

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

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

一共有三个节点: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,
  });
});

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

您的尝试有两个问题:

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

我们开始:

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