typescript - 使用 TypeScript 泛型作为自己的参数,或将其指定为自己的默认参数

标签 typescript generics

我有以下 ItemBase 接口(interface)和从其扩展的多个其他递归 xItem 接口(interface):

interface ItemBase<Children extends ItemBase<Children>> {
  x: string;
  y: number;
  children: Children[];
}

interface FooItem extends ItemBase<FooItem> {
  foo: boolean;
}

interface BarItem extends ItemBase<BarItem> {
  bar: "b" | "a" | "r";
}

我现在想引用 ItemBase 并将其自身作为自己的参数:

const transformItem = (item: ItemBase<ItemBase>) => { ... }
//                                    ^
// TS2314: Generic type 'ItemBase ' requires 1 type argument(s).

但这不起作用,因为因为我没有指定内部 ItemBase 的参数(并且显然不能继续将这些参数指定为无穷大)。

更好的方法是将自身提供为 ItemBase 的默认参数...我尝试了两种方法,但每种方法都会遇到自己的错误:

interface ItemBase<Children extends ItemBase<Children> = ItemBase<Children>> {
//                                                                ^
// TS2744: Type parameter defaults can only reference previously declared type parameters.
  x: string;
  y: number;
  children: Children[];
}
interface ItemBase<Children extends ItemBase<Children> = ItemBase> {
//                                                       ^
// TS2716: Type parameter 'Children' has a circular default.
  x: string;
  y: number;
  children: Children[];
}

一个明显的解决方法是创建一个单独的界面来表达我的自引用基础:

interface BaseItem extends ItemBase<BaseItem> {}
const transformItem = (item: BaseItem) => { ... }

但这更像是一种黑客行为,因为其他项目并没有真正继承它。

我还有哪些其他选择?

最佳答案

根据您的使用案例,您可能需要使用 polymorphic this types 。在 interfaceclass声明时,您可以使用名为 this 的类型引用“当前”子类型。就好像this是一个“隐式”generic类型参数,其行为类似于 interface Foo<T extends Foo<T>> 中的递归约束(又名 "F-bounded polymorphism" ) 。它使您不必显式使用泛型:

interface ItemBase {
    x: string;
    y: number;
    children: this[];
}

interface FooItem extends ItemBase {
    foo: boolean;
}

interface BarItem extends ItemBase {
    bar: "b" | "a" | "r";
}

要查看它的实际效果,以下是一些可能的用途:

const fooItem: FooItem = {
    x: "a",
    y: 1,
    foo: true,
    children: [{
        x: "b", y: 2, foo: true, children: []
    }]
}

function processItem(item: ItemBase) {
    console.log(item.x.toUpperCase());
    console.log(item.y.toFixed(2));
    item.children.forEach(i => processItem(i));
}

processItem(fooItem); // A, 1,00, B, 2.00

在某些情况下,多态 this很难使用,但是在问题中没有更具体的用例,我不确定您是否会遇到它们。

Playground link to code

关于typescript - 使用 TypeScript 泛型作为自己的参数,或将其指定为自己的默认参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67307364/

相关文章:

java - Generic 中的类型转换错误

java - 覆盖泛型方法

generics - 类型推断: Using generic methods with implicit type conversion

javascript - 扁平化同步 Angular promise

typescript - typescript 中的抽象泛型类

javascript - 使用 typescript generic 检查对象是否为空

java - 如何在非泛型方法中指定两个通配符在语义上相等?

javascript - TypeError : <. ..> 不是一个函数

angular - 如何对 Angular 中的 void 函数进行单元测试?

swift - swift 中的 T.Type 是什么