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

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

Bug报告

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

🔎 搜索词

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

问题代码

interface IdLabel {
  id: number /* some fields */;
}
interface NameLabel {
  name: string /* other fields */;
}
type NameOrId<T extends number | string> = T extends number
  ? IdLabel
  : NameLabel;
function createLabelBad<T extends number | string>(idOrName: T): NameOrId<T> {
  if (typeof idOrName === 'string') {
      return {name: idOrName}; // TS2322
  }
  return {id: idOrName}; // TS2322
}
function createLabelGood<T extends number | string>(idOrName: T): NameOrId<T> {
  if (typeof idOrName === 'string') {
      const nameLabel: NameLabel = {name: idOrName};
      return nameLabel as any;
  }
  const idLabel: IdLabel = {id: idOrName};
  return idLabel as any;
}

🙁 实际行为

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

🙂 预期行为

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

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.

function createLabel<T extends number | string>(idOrName: T): NameOrId<T> {
  if (typeof idOrName === 'string') {
      return {name: idOrName} as NameOrId<T>;
  }
  return {id: idOrName} as NameOrId<T>;
}
eagi6jfj

eagi6jfj3#

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

0tdrvxhp

0tdrvxhp4#

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

function createLabel<T extends number | string>(idOrName: T): NameOrId<T>
function createLabel<T extends number | string>(idOrName: T) {  
  if (typeof idOrName === 'number') {
    return { id: idOrName };
  } else {
    return { name: idOrName };
  }
}

TSPlayground链接

cgyqldqp

cgyqldqp5#

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

type SimpleConditionalType<T> = T extends string ? string : never;

function template<T extends string>(): SimpleConditionalType<T> {
  return 'abc' // Error: Type '"abc"' is not assignable to type 'SimpleConditionalType<T>'.
}

function str<T extends string>(): SimpleConditionalType<string> {
  return 'abc' // ok
}

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

相关问题