类型可分配给类型“类型”的约束,但是可以用约束“类型”的其他子类型实例化“类型”

时间:2020-04-11 17:51:56

标签: typescript typescript-generics

已经有一些这样的问题。但是我认为这更加具体。

请参见以下示例:

interface Body {
  legs: number;
}

interface Kingdom {
  animalia: {
    sound: string; // meow..
    body: Body;
  };
}

function GetBody<
  Category extends keyof Kingdom,
  B extends Kingdom[Category]["body"]
>(cat: Category): B {
  // stuff..
  return { legs: 4 }; // <==== Error!
}

// called like: GetBody('animalia').legs

错误提示:

Type '{ legs: number; }' is not assignable to type 'B'.
  '{ legs: number; }' is assignable to the constraint of type 'B', 
  but 'B' could be instantiated with a different subtype of constraint 'Body'.ts(2322)

我在这里做错了什么?我该如何解决?

1 个答案:

答案 0 :(得分:1)

您的问题是B extends Kingdom[Category]["body"] 不是意味着BKingdom[Category]["body"],相反,这意味着B必须是可分配的Kingdom[Category]["body"]

因此,正如@Aluan指出的那样,像{legs: number, eyes: 2}这样的类型对于B是完全有效的。 {legs: number, eyes: 2} 扩展了 Kingdom[Category]["body"]。 这意味着您返回的对象{ legs: 4 }是不够的。如果B正好是Kingdom[Category]["body"],那将是完美的,但这并非总是如此。

根据您的情况,不需要通用。确实,使用一个错误,因为您确实需要Kingdom[Category]["body"]

function GetBody<
  Category extends keyof Kingdom,
>(cat: Category): Kingdom[Category]["body"] {
  return { legs: 4 };
}

注意:已经有一个称为Body的TS接口。更改您的名字。