【问题标题】:Using `import type` statement to fix circular dependency reference error使用 `import type` 语句修复循环依赖引用错误
【发布时间】:2017-04-20 08:35:36
【问题描述】:

假设我有两个文件,A.js 和 B.js。两者都需要像这样相互引用。

A.js

import { B } from "b"

export class A {
  constructor(public name: string) {}
}

let b = new B();
b.print(new A("This is a random name"));

B.js

import { A } from "a"

export class B {
  print(a: A) {
    console.log(a.name);
  }
}

上面的示例将创建一个循环引用,该引用当前在我使用的 JavaScript 运行时中不起作用。 B.js 文件实际上只需要类型信息,而不需要实际的导出对象)。我希望 A.js 中的类型进行静态类型检查。这可能吗?

【问题讨论】:

  • 你不能把class A移动到一个不同的文件,当你想做b.print(...)的时候把它们都导入吗?
  • 或者更好的是,只需为 B 制作一个放在不同文件中的接口,并让其他两个文件都使用它。
  • 这就是循环依赖的定义。你只需要打破这种依赖...A 没有理由需要引用B。将其余代码移到别处。
  • 如果您使用的是 typescript,请使用类型

标签: typescript


【解决方案1】:

这现在可以在 TypeScript 2.9 中直接实现。

type MyType = import('mymodule').MyType;
const myValue: import('mymodule').MyType;

【讨论】:

  • 这太完美了,非常感谢。我最终做了mutation: keyof typeof import('./mutations'),
【解决方案2】:

更新:这个答案可能会过时 as soon as TypeScript 3.8 is released

你不需要做任何特别的事情来只从模块a导入类型信息。

Typescript 会为你做这件事 - 如果模块 b 需要表单 a 的唯一东西是类型信息,编译文件 b.js 将没有 require("./a") 语句,也就是说,它不会有运行时依赖a。引用typescript handbook:

编译器检测每个模块是否在发出的 JavaScript。如果模块标识符仅用作类型的一部分 注释并且从不作为表达式,则不需要调用 为该模块发出。

我刚试过:

文件a.ts

import { B } from "./b"

export class A {
    constructor(public name: string) {}
}

let b = new B();
b.print(new A("This is a random name"));

文件b.ts

import { A } from './a';

export class B {
    print(a: A) {
        console.log(a.name);
    }
}

一起编译

tsc a.ts b.ts

这是结果 b.js

"use strict";
var B = (function () {
    function B() {
    }
    B.prototype.print = function (a) {
        console.log(a.name);
    };
    return B;
}());
exports.B = B;

看到了吗?没有require("./a"),不像a.js 包含

var b_1 = require("./b");

很可能,您在问题中发布的示例代码不完整,并且真正的 b 模块在运行时依赖于 a - 找出它的位置并摆脱它,您就不会遇到这个问题.

【讨论】:

  • 很好的答案!我完全错过了这个,谢谢你让我知道!您是对的,因为我的示例对于我的“真正”问题来说过于简化了。
  • 如果“仅类型”导入有一些副作用怎么办?要求语句会被删除吗?如果是,TS 是如何确定的?
  • 我不认为编译器可以确定某些东西是否有副作用。如果模块有副作用,最好明确并使用import for side-effects only 形式的导入语法,以及来自同一模块的任何命名或默认导入(如果有)。
  • 奇怪我想知道这是否改变了,因为我看到 typescript 发出一个 js 要求,现在永远不会读取。
【解决方案3】:

从 TypeScript 3.8 开始,使用 import type:

import type { SomeThing } from "./some-module.js";

export type { SomeThing };

参考:

https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#type-only-imports-exports

【讨论】:

    【解决方案4】:

    你在这里使用了 [typescript] 标签,所以我假设你使用的是 typescript。

    将此设为单向街道。杀死循环依赖。我可能会将它移动到 1 个文件中,但您仍然可以像这样拆分它。

    a.ts(只是一个界面)

    export interface A {
        name: string;
        new (name: string);
    }
    

    b.ts(实现)

    import { A } from 'a';
    
    export class B implements A {
        /*...*/
    }
    

    【讨论】:

    • 我当然可以将类移动到其他文件(或进行其他重构)以解决问题,但在这种情况下这不是问题。
    猜你喜欢
    • 1970-01-01
    • 2016-02-14
    • 1970-01-01
    • 1970-01-01
    • 2017-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多