我在Typescript 中有这样的代码:

type DormNodePredicate = DormEdge | (() => DormNode<DormNodePredicateRecord>);
interface DormNodePredicateRecord {
  [key: string]: DormNodePredicate;
}

export class DormNode<DNPR extends DormNodePredicateRecord> {
  constructor(public preds: DNPR) {}
}

enum PredicateType {
  STRING = "string"
}

export class DormEdge<AsArray extends boolean = false> {
  constructor(private predType: PredicateType, asArray: AsArray = false as AsArray) {}
}

const Audit = new DormNode({
  user: () => User
}) 

const User = new DormNode({
  name: new DormEdge(PredicateType.STRING),
  audits: () => Audit
});

我的问题是,AuditUser都被推断为any类型.我需要能够从用户引用审核,这样我才能达到深度递归,如:Audit.preds.user().preds.audits()....当然,这只是一个例子,我在现实世界中的用例要复杂和深刻得多.我怎么才能解决这个问题呢?

作为附注,在代码的这一部分:

export class DormEdge<AsArray extends boolean = false> {...}

当我从泛型中go 掉= false,我就能够做我想做的事情了.我不太明白在幕后到底发生了什么.如果有人能帮我解决这个问题,我将不胜感激.作为参考,我使用的是typescript@5.3.3.谢谢!

推荐答案

TypeScript的类型推断算法本质上是启发式的,如果它在try 确定类型时进入循环,它将放弃隐式any. 该算法在处理"公共"循环时,适用于广泛的现实世界代码. 但它不能对所有情况都起作用,这将需要对推理算法进行全面判断以实现microsoft/TypeScript#30134中讨论的full 101,这不太可能发生,因为虽然这样做是"正确的",但它需要大量的工作,并且可能导致许多常见情况下的IDE体验明显变差.

因此,有时会出现编译器无法正确分析的代码,因为它遇到了循环.对于一个人来说,如何决定类型并避免这样的循环通常是完全显而易见的,但这并不能真正帮助推理.有很多类型脚本GitHub的问题,有人报告说这样的循环是错误的,但这个问题被标记为设计限制或不是缺陷, comments 说,这是我们在不花费超出我们承受能力的资源的情况下所能做的最好的事情.例如,请参见microsoft/TypeScript#49837microsoft/TypeScript#45213microsoft/TypeScript#35546.

在这种情况下,通常的建议是找到一个地方,编译器找到一个循环和annotate与适当的类型. 也就是说,你告诉编译器类型是什么,它可以继续判断它.有很多方法可以做到这一点.在你的例子中,看起来有真正的递归类型,所以你需要首先定义它们:

type Audit = DormNode<{ user: () => User }>
type User = DormNode<{ name: DormEdge, audits: () => Audit }>;

现在,您可以对AuditUser中的至少一个进行注释,并且它是有效的:

const Audit: Audit = new DormNode({
  user: () => User
})
const User: User = new DormNode({
  name: new DormEdge(PredicateType.STRING),
  audits: () => Audit
});

是的,这对你来说比你想要的工作要多.也许有一些稍微不那么冗长的注释可以使用,但不管会发生什么情况,推荐的方法是自己使用cut the knot,而不是说服编译器将其解开.

Playground link to code

Typescript相关问答推荐

Tailwind CSS样式不在Svelte应用程序中呈现

为什么缩小封闭内部不适用于属性对象,但适用于声明的变量?

APP_INITIALIZER—TypeError:appInits不是函数

动态调用类型化函数

在动态对话框中使用STEP组件实现布线

React重定向参数

仅针对某些状态代码重试HTTP请求

使用TypeScrip根据(可选)属性推断结果类型

如何在Typescript 中组合unions ?

防止重复使用 Select 器重新渲染

@TANSTACK/REACT-QUERY中发生Mutations 后的数据刷新问题

类型脚本中参数为`T`和`t|unfined`的重载函数

来自枚举的<;复选框和组件列表

Typescript泛型调用对象';s方法

T的typeof键的Typescript定义

如何知道使用TypeScript时是否在临时工作流内运行

如何在Vuetify 3中导入TypeScript类型?

如何使用 AWS CDK 扩展默认 ALB 控制器策略?

使用 fp-ts 时如何使用 TypeScript 序列化任务执行?

如何强制对象数组中的对象属性具有非空字符串值?