【问题标题】:How to Implement an interface with conditional types in TypeScript如何在 TypeScript 中实现具有条件类型的接口
【发布时间】:2022-01-15 20:01:56
【问题描述】:

在个人项目中,我遇到了 TypeScript 条件类型的问题。我对 TypeScript 文档中的条件类型有基本的了解。我希望下面的设置可以工作,但它会给出类型错误。

基本上,我正在尝试为从磁盘加载的树节点定义一个接口。这意味着某些节点可能由于缺少文件等而无法正确加载。因此任何节点实现都包含ContentError

interface Content {
  data: number;
}

interface Error {
  code: string;
}

export interface TreeNode<T extends Content | Error> {
  getValue(): T extends Content ? number : string;
}

class ValueNode<ValueType extends Content> implements TreeNode<ValueType> {
  private readonly value: number;
  public constructor(value: number) {
    this.value = value;
  }
 
  public getValue(): number {
    return this.value;
  }
}

我希望getValue 方法的实现将被允许返回string,因为该接口是用扩展Content 的类型实现的。但是我收到了这种类型的错误:

  • ValueNode&lt;ValueType&gt; 类型中的属性getValue 不能分配给基本类型TreeNode&lt;ValueType&gt; 中的相同属性。
    • 类型() =&gt; number 不可分配给类型() =&gt; ValueType extends Content ? number : string
      • 类型number 不可分配给类型ValueType extends Content ? number : string

很清楚,我做错了。实现我的目标的正确方法是什么?

【问题讨论】:

  • 鉴于ValueType 是一个类型参数,你为什么不在ValueNode&lt;...&gt; 中使用它?
  • 顺便说一句,Error 是一个内置类型,所以你应该给你的interface Error 一个不同的名字,比如interface MyError 左右。
  • Typescript 非常适合将 JavaScript 制作成 c#。而且,这对节点很有用。 JavaScript 没有 "types" 以同样的方式。 @dai 编辑了错误以使其更加透明。
  • @wahwahwah 请原谅?你所说的与手头的问题没有任何关系。
  • 看起来 class ValueNode implements TreeNode&lt;Content&gt; 就是您要找的东西..

标签: javascript typescript


【解决方案1】:

作为@Dai pointed out,最好不要shadow内置Error类型(这样你就可以在你的模块中使用它)。

这里有两种选择:

TS Playground link

interface ContentValue {
  data: number;
}

interface ErrorValue {
  code: string;
}

export interface ValueGetter<T> {
  getValue(): T;
}

class ValueNode<T extends ContentValue> implements ValueGetter<ContentValue['data']> {
  public constructor(private readonly value: T) {}
 
  public getValue(): number {
    return this.value.data;
  }
}

// or
class SimpleValueNode<T extends ContentValue> {
  public constructor(private readonly value: T) {}
 
  public getValue(): number {
    return this.value.data;
  }
}

【讨论】:

  • 我认为 OP 仍然打算让 ValueNode 成为一个 open 泛型类型...
  • @Dai 你的意思是喜欢this
  • 差不多,但是您的class ValueNode 需要将T 限制为ContentValue 并禁止ErrorValue
  • @jsejcksn 是的!我在原始问题中有错字。 value 内部的 TreeNode 应该是通用的。您的示例有效且有意义。但我不明白为什么它不起作用,当它看起来像 this
  • @lishaak 我已经更新了我的答案。 (我不清楚如果要对单个方法实现进行注释,为什么需要 TreeNode 接口。)其中一种变体对你有用吗?
猜你喜欢
  • 1970-01-01
  • 2021-02-21
  • 1970-01-01
  • 2019-06-27
  • 2022-01-27
  • 2021-07-20
  • 2021-05-03
  • 1970-01-01
相关资源
最近更新 更多