使用 class 表达式时是否支持循环引用?

Are circular references supported when using class expressions?

我在使用 class 表达式时遇到循环引用的一些问题。我正在动态生成 classes 并尝试正确输入它们。

循环引用与 class 声明一起工作。

我想做的事情可行吗?

// Works
class X {
  y?: Y;
}
class Y {
  x?: X;
}

// Works without circular ref
const I = class {
};
const J = class {
  i?: typeof I;
};


// Doesn't work  with circular ref
const A = class {
  b?: typeof B;
};
const B = class {
  a?: typeof A;
};

Typescript playground


上下文更新

我正在尝试创建一个从给定 "model definition" 生成 class 的函数。这个模型定义有布尔值、字符串、数字等类型,但也可能与另一个模型有关系。

只要不引入循环引用,它在类型方面就可以正常工作。

这个 playground 说明了我正在努力完成的事情。

Typescript 是一种静态类型语言,这意味着您必须事先定义类型,不能动态生成类型,但是,您可以使用泛型来实现您的目标。

在对 TypeScript 语言规范进行了一些研究之后,我认为不幸的是无法将循环类型引用与 class 表达式一起使用。

我无法根据您提供的信息判断您的一般方法是否正确 - 例如如果你真的需要 class 表达式、动态模型或者它是一个 XY 问题。那是另一个话题了。我在这里尝试的是回答,为什么您使用循环类型引用和 class 表达式的方法会产生编译错误。

当 class 表达式 AB 通过 typeof A/ typeof B 相互引用时,您使用 typeof 创建类型别名操作员。对于类型别名,规范说:

It is an error for the type specified in a type alias to depend on that type alias. Link

不过,还声明了以下内容:

Note that object type literals, function type literals, and constructor type literals do not depend on types referenced within them and are therefore permitted to circularly reference themselves through type aliases. Link

我是这样解释这个语句的:如果你 wrap/substitute 你的模型在上面提到的类型文字之一中引用,那么有循环引用是可以的。

Modified Playground

在此示例中,我将您的模型 class 构造包装在工厂方法/函数类型文字中。它仅用于演示目的和工作,请随意以您自己的方式解释它。

假定您可以稍微调整 FieldDescriptor

type FieldDescriptor = keyof MapSchemaTypes | (() => ModelConstructor<any>);

关于 class 声明:我想它们在您的示例中有效,因为 TypeScript 首席开发人员 Recursive Types. See also this statement 支持声明和接口。

希望这对您的情况有所帮助。