如何扩展递归打字稿接口以进行类型检查?

时间:2019-03-18 12:49:10

标签: typescript

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

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

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: [],
    },
  ],
};

1 个答案:

答案 0 :(得分:0)

如果您希望children与当前接口属于同一类型,则最简单的解决方案可能是使用多态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: [],
    },
  ],
};