TypeScript 条件类型文档缺少对其使用至关重要的信息,

vmdwslir  于 9个月前  发布在  TypeScript
关注(0)|答案(5)|浏览(94)

Bug报告

条件类型的文档缺少关于限制的重要信息。如果有人希望使用它们,会感到沮丧,因为它们不能按照人们的预期工作。文档中使用throw "unimplemented";并且没有关于实际实现时可能出现的问题的警告。
经过几个小时的尝试和搜索,我已经强烈地认为这是一个bug,我发现这是一个设计限制 - #22735

🔎 搜索词

条件类型不起作用,TS2322,条件类型,损坏的条件类型

问题代码

  1. interface IdLabel {
  2. id: number /* some fields */;
  3. }
  4. interface NameLabel {
  5. name: string /* other fields */;
  6. }
  7. type NameOrId<T extends number | string> = T extends number
  8. ? IdLabel
  9. : NameLabel;
  10. function createLabelBad<T extends number | string>(idOrName: T): NameOrId<T> {
  11. if (typeof idOrName === 'string') {
  12. return {name: idOrName}; // TS2322
  13. }
  14. return {id: idOrName}; // TS2322
  15. }
  16. function createLabelGood<T extends number | string>(idOrName: T): NameOrId<T> {
  17. if (typeof idOrName === 'string') {
  18. const nameLabel: NameLabel = {name: idOrName};
  19. return nameLabel as any;
  20. }
  21. const idLabel: IdLabel = {id: idOrName};
  22. return idLabel as any;
  23. }

🙁 实际行为

文档中省略了非常重要的信息。这导致了不必要的沮丧、头痛和浪费时间。

🙂 预期行为

在文档中提到关于条件类型的限制的重要信息,可能还会提供一些解决方法,而不是throw "unimplemented";

nle07wnf

nle07wnf1#

See also #33912

rkue9o1l

rkue9o1l2#

See also #33912
Thank you! The workaround from that issue is the thing I would love to see in the documentation! With that information I am now able to make it much cleaner and safer.

  1. function createLabel<T extends number | string>(idOrName: T): NameOrId<T> {
  2. if (typeof idOrName === 'string') {
  3. return {name: idOrName} as NameOrId<T>;
  4. }
  5. return {id: idOrName} as NameOrId<T>;
  6. }
eagi6jfj

eagi6jfj3#

感谢@psznm向我们分享了这个解决方法(这里是TypeScript playground的链接)。当前的文档没有充分解决这个问题,我花了两个小时才解决它...非常感谢!

0tdrvxhp

0tdrvxhp4#

我刚来这里写同样的东西,发现了这个问题!
既然这是一个已知的限制/错误,文档至少应该提到推荐的解决方法,并实际为 createLabel 方法提供实现,而不是简单地抛出错误。
仅供参考,除了 @psznm 的回答中你输入函数的返回值,你还可以使用条件类型化函数作为重载,并编写没有返回类型的函数(推断)。这也会起作用。
具体来说:

  1. function createLabel<T extends number | string>(idOrName: T): NameOrId<T>
  2. function createLabel<T extends number | string>(idOrName: T) {
  3. if (typeof idOrName === 'number') {
  4. return { id: idOrName };
  5. } else {
  6. return { name: idOrName };
  7. }
  8. }

TSPlayground链接

cgyqldqp

cgyqldqp5#

我也遇到了这个问题。与其他人一样,当前的文档非常误导,因为它省略了实现部分。作为读者,我错误地认为实现是如此常见,以至于不需要详细说明,并且可以在函数内部正确推断出类型。
这个bug非常严重,让我觉得我快要疯了。甚至以下示例也失败了:

  1. type SimpleConditionalType<T> = T extends string ? string : never;
  2. function template<T extends string>(): SimpleConditionalType<T> {
  3. return 'abc' // Error: Type '"abc"' is not assignable to type 'SimpleConditionalType<T>'.
  4. }
  5. function str<T extends string>(): SimpleConditionalType<string> {
  6. return 'abc' // ok
  7. }

这个示例还被用在了 a short (and otherwise excellent) talk by Anders 中,那里的实现也被省略了!😄

相关问题