简体   繁体   中英

How to extend a recursive typescript interface for type checking?

I want to write a base interface which has self referential children and I want to extend that interface so that children become the type of new interface.

Example of solution I tried using generics:

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
}

I can fix this only in last extend without using type arguments:

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

But this interface can no longer be extended with new properties being part of children.

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

Is there a solution I am missing?

Another explanation:

I want to operate on interface:

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

Then I want to extend above interface and operate on this.

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

Then I want to extend above interface and operate on this.

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

If you want children to be of the same type as the current interface, the simplest solution is probably to use 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: [],
    },
  ],
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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