首页 > 解决方案 > 如何扩展用于类型检查的递归打字稿接口?

问题描述

我想编写一个具有自引用子级的基本接口,并且我想扩展该接口,以便子级成为新接口的类型。

我尝试使用泛型的解决方案示例:

interface ICommentBase<T> {
  author: string;
  children: T[];
}

interface IComment<T> extends ICommentBase<T> {
  upvotes: number;
}

interface ICommentSuper<T> extends IComment<T> {
  reported: boolean;
}

// error because IComment needs a type argument etc.
function readChildrenUpvotes(comment: IComment<IComment>) {
  // do something
}

我只能在最后一个扩展中解决这个问题,而不使用类型参数:

// now no error will show when using this interface
interface ICommentSuperTwo extends IComment<ICommentSuperTwo> {
  reported: boolean;
}

但是这个接口不能再通过新属性作为子元素的一部分进行扩展。

// children[0].creationDate will throw error because creationDate
// does not exist on interface ICommentSuperTwo
interface ICommentSuperDuper extends ICommentSuperTwo {
  creationDate: string;
}

有我缺少的解决方案吗?

另一种解释:

我想在界面上操作:

const baseComments = {
  author: "anon",
  children: [
    {
      author: "anon",
      children: [],
    },
  ],
};

然后我想扩展上面的接口并对此进行操作。

const comments = {
  author: "anon",
  upvotes: 0,
  children: [
    {
      author: "anon",
      upvotes: 0,
      children: [],
    },
  ],
};

然后我想扩展上面的接口并对此进行操作。

const improvedComments = {
  author: "anon",
  upvotes: 0,
  reported: false,
  children: [
    {
      author: "anon",
      upvotes: 0,
      reported: false,
      children: [],
    },
  ],
};

标签: typescript

解决方案


如果您想children与当前接口的类型相同,最简单的解决方案可能是使用 polymorphic this

interface ICommentBase {
  author: string;
  children: this[];
}

interface IComment extends ICommentBase {
  upvotes: number;
}

interface ICommentSuper extends IComment {
  reported: boolean;
}

function readChildrenUpvotes(comment: IComment) {
  // do something
}

const baseComments: ICommentBase = {
  author: "anon",
  children: [
    {
      author: "anon",
      children: [],
    },
  ],
};

const comments: IComment = {
  author: "anon",
  upvotes: 0,
  children: [
    {
      author: "anon",
      upvotes: 0,
      children: [],
    },
  ],
};

const improvedComments: ICommentSuper = {
  author: "anon",
  upvotes: 0,
  reported: false,
  children: [
    {
      author: "anon",
      upvotes: 0,
      reported: false,
      children: [],
    },
  ],
};

推荐阅读