【问题标题】:Why is “declare var angular” necessary when using Typescript with AngularJS?为什么在使用 Typescript 和 AngularJS 时需要“声明 var angular”?
【发布时间】:2019-05-08 20:42:05
【问题描述】:

我有一个功能性 AngularJS 1.7 应用程序,其中我的所有代码都是用 TypeScript 编写的。但总有一些事情困扰着我。

在我的 app.module.ts 文件中,我有一点丑陋:
declare var angular;
为了
this.app = angular.module('app'...
转译和运行。

我尝试过的事情:

1) 将declare var angular; 替换为
import angular from "angular";
转译很好,但随后浏览器抱怨
Uncaught (in promise) TypeError: angular_1.default.module is not a function

2) 将declare var angular; 替换为
import * as angular from "angular";
也可以正常编译,但浏览器会出现类似的错误:
Uncaught (in promise) TypeError: angular.module is not a function

3) 将declare var angular; 替换为
import ng from "angular";
然后使用 ng.angular.moduleng.module 根本不会转译。

我确定我已经尝试了其他一些方法,但我能够让事情正常工作的唯一方法是使用 declare var angular;

这一切都很好,但这对我来说肯定闻起来很糟糕。为什么我必须这样做?我究竟做错了什么?有没有更好的方法?


详情:

  • Visual Studio 2017/2019
  • TypeScript 3.3
  • SystemJS(不是 RequireJS)
  • AngularJS 1.7.8
  • @types/angular 1.6.54

package.json

"devDependencies": {
    "@types/angular": "^1.6.54",
    ...
},
"dependencies": {
    "angular": "~1.7.8",
    ...
}

tsconfig.json

{
    "compileOnSave": true,
    "compilerOptions": {
        "baseUrl": ".",
        "paths": {
            "*": [ "node_modules/types/*", "node_modules/*" ],
        },
        "module": "system",
        "target": "es6",
        "sourceMap": true,
        "lib": [ "es6", "dom" ],
        "allowSyntheticDefaultImports": true,
        "outFile": "./app/everything.js",
        "moduleResolution": "node",
        "types": [
            "angular",
            "jquery"
        ]
    },
    "include": ["app/**/*"],
    "exclude": ["node_modules", "lib"],
    "strict": true
}

app.module.ts

declare var angular;
...
export class App {
    app: ng.IModule;

    constructor() {
        this.app = angular.module('app', [
        ...
        ]);
    }

    public run() {
        this.app.run([
        ...
        ]);
        ...
    }

index.html

...
<script src="lib/systemjs/system.js"></script>
<script src="lib/angular/angular.min.js" type="text/javascript"></script>
...
<script src="app/everything.js" type="text/javascript"></script>

<script>
    System.config({
        map: {
            "angular": "lib/angular",
            ...
        },
        packages: {
            "angular": { main: "angular.min.js", defaultExtension: "js" },
            ...
        }
    });
    System.import("app.module")
        .then(function (app) {
            let a = new app.App();
            a.run();

            angular.element(function () {
                angular.bootstrap(document, ['app']);
            });
        });
</script>

【问题讨论】:

  • 请花点时间阅读How to Ask,尤其是标题为“写一个总结具体问题的标题”的部分。你现在的头衔...没有那样做:)。
  • 是的,标题不太好。编辑了它,希望它现在更好。谢谢!

标签: angularjs typescript systemjs


【解决方案1】:

您的 Typescript 类型 @types/angular 查找 angular 变量以附加它们的类型。

通常,您会像这样导入 angular:import angular from "angular",并且类型将应用于您刚刚创建的 angular 变量,一切都会正常工作。

但是,您已经在 HTML &lt;script&gt; 中全局加载 Angular。在这种情况下,您不想import angular from "angular",因为那样您将多次加载 Angular,并且事情可能会中断。

通过写declare var angular,你只是告诉 Typescript 相信你它的存在,即使它没有看到它被导入到这个文件的范围内。

这意味着

  • Typescript 不会抱怨 Angular 未定义。
  • @types/angular 将附加到您的变量 angular

当您进入运行时,假设 angular 确实存在于 window 上,那么它将起作用。

当您迁移到 Webpack 或 SystemJS 之类的打包程序时,这是一个需要解决的问题。从 index.html &lt;script&gt; 中删除全局 Angular 后,您可以导入 TS 文件并删除 declare var

【讨论】:

  • 嗯。所以'declare var angular;'也在做打字吗?我的印象是,它只是简单地声明“角度”,这样 TypeScript 就不会对其进行任何类型检查......
  • 我在回答中添加了更多细节。
  • 感谢您添加更多详细信息!我在 HTML 中全局加载了 Angular,因为我使用了其他与 Angular 相关的东西,比如 angular-route,并且需要首先加载主 Angular.js 文件。它们没有在我的 TypeScript 代码中使用,所以我只是加载它们而不是 importing 它们。从那以后,我花时间将所有这些添加到 SystemJS 配置中,然后尝试将它们导入到我的 TypeScript 代码中,以便 SystemJS 以正确的顺序加载它们,但我得到了同样的错误。我发现很多这令人费解。如果我不能使用 @types/angular/index.d.ts 有什么意义?
  • 你的导入一定有问题。 Console.log 角度,看看你得到了什么。显然不是以模块为方法的对象。
猜你喜欢
  • 1970-01-01
  • 2016-03-26
  • 2023-03-25
  • 2011-06-13
  • 2020-01-11
  • 1970-01-01
  • 2019-12-12
  • 1970-01-01
  • 2016-08-19
相关资源
最近更新 更多