简体   繁体   English

如何根据object属性值应用接口

[英]How to apply the interface according to the object property value

I wrote it again by summarizing the contents of the article. 我通过总结文章的内容再次写了它。

I want to know how to apply the interface according to the object property value.我想知道如何根据 object 属性值应用接口。

I wrote a simple example code below.我在下面写了一个简单的示例代码。

There are a total of three nodes: root, dept, and user.一共有三个节点:root、dept、user。

The type corresponding to each node is specified.指定每个节点对应的类型。 Therefore, we want the interface to be designated according to the object type property.因此,我们希望根据 object 类型属性指定接口。

However, you can see that you are manually affirming the type because you have not found a solution.但是,您可以看到您正在手动确认类型,因为您还没有找到解决方案。

In order to solve this problem, I think it should be solved with an index type rather than a conditional type.为了解决这个问题,我认为应该用索引类型而不是条件类型来解决。

The reason is that the conditional type is expected to be calculated and returned according to the generic type parameter, but the current problem should be calculated based on the existing type rather than receiving the type parameter.原因是条件类型是期望根据泛型类型参数计算返回的,但是当前的问题应该是根据现有类型计算而不是接收类型参数。

However, the problem could not be solved even with two methods.但是,即使使用两种方法也无法解决问题。 Any help would be appreciated ♂️任何帮助将不胜感激♂️

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

I know how to do it by using type s, not interface s.我知道如何使用type s,而不是interface s。

Your attempt has two problems:您的尝试有两个问题:

  1. by using type, you can leverage the discriminated unions (notice the Node type as the union of the three possible cases).通过使用类型,您可以利用区分联合(注意Node类型作为三种可能情况的联合)。
  2. for the array methods such as filter and forEach , the inferral algorithm isn't smart enough to understand what is the requested type, hence you have to use a simple for and a if .对于filterforEach等数组方法,推断算法不够聪明,无法理解请求的类型,因此您必须使用简单forif

Here we go:这里我们 go:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM