Тип можно назначить ограничению типа «Тип», но экземпляр «Тип» можно создать с другим подтипом ограничения «Тип» - PullRequest
0 голосов
/ 11 апреля 2020

Есть несколько вопросов, уже заданных, как это. Но я думаю, что это немного конкретнее c.

Пожалуйста, посмотрите этот пример:

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 Ответ

1 голос
/ 11 апреля 2020

Ваша проблема в том, что B extends Kingdom[Category]["body"] не означает , что означает B Kingdom[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"], но это не всегда так.

В вашей ситуации нет необходимости в обобщенном c. Действительно, использовать его неправильно, потому что вам нужно ровно Kingdom[Category]["body"]:

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

ACHTUNG : интерфейс TS уже называется Body. Измени свое имя.

...