javascript - 如何使用常规脚本标签运行模块 typescript 输出?

标签 javascript typescript

我对 JavaScript 生态系统不是很熟悉,所以不太确定我的标题是否正确......我在大量“谷歌搜索”的帮助下用纯 ES6 编写了一个简单的应用程序,但我一直在获取类型错误,因此决定切换到 TypeScript。

一开始我很兴奋,

let blah: String = "hello world";
console.log(blah);

并运行tsc blah.ts输出

var blah = "hello world";
console.log(blah);

这看起来很简单,我只是包含

<script src="ts/blah.js"></script>

并且 console.log 将会打印。

我决定利用模块来看看如何构建更大的东西,所以我创建了一个 lib.ts

export class StringUtil {

    private rawValue: String;

    constructor(input: String) {
        this.rawValue = input;
    }

    upper(): String {
        return this.rawValue.toUpperCase();
    }

}

并将我的原始示例更新为

import { StringUtil } from "./lib";

let blah: String = "hello world";
// console.log(blah);
console.log(new StringUtil(blah).upper());

运行 tsc *.ts 现在输出:

"use strict";
exports.__esModule = true;
var lib_1 = require("./lib");
var blah = "hello world";
// console.log(blah);
console.log(new lib_1.StringUtil(blah).upper());

刷新浏览器,我现在得到

Uncaught ReferenceError: exports is not defined
    at blah.js:2

所以经过大量阅读后,我看到很多人建议我添加一个 TypeScript 配置文件,我这样做了,

{
    "compilerOptions": {
        "target": "es5",
        "module": "commonjs",
        "sourceMap": true,
        "watch": true
    }
}

输出完全相同,但仍然有相同的错误:

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var lib_1 = require("./lib");
var blah = "hello world";
// console.log(blah);
console.log(new lib_1.StringUtil(blah).upper());
//# sourceMappingURL=blah.js.map

有人建议使用 amd 作为模块类型:

{
    "compilerOptions": {
        "target": "es5",
        "module": "amd",
        "sourceMap": true,
        "watch": true
    }
}

现在输出:

define(["require", "exports", "./lib"], function (require, exports, lib_1) {
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    var blah = "hello world";
    // console.log(blah);
    console.log(new lib_1.StringUtil(blah).upper());
});
//# sourceMappingURL=blah.

浏览器提示:

Uncaught ReferenceError: define is not defined
    at blah.js:1

切换到模块的“umd”,浏览器错误消失,但由于输出位于我不知道如何调用的匿名函数内,因此 console.log 不再触发

(function (factory) {
    if (typeof module === "object" && typeof module.exports === "object") {
        var v = factory(require, exports);
        if (v !== undefined) module.exports = v;
    }
    else if (typeof define === "function" && define.amd) {
        define(["require", "exports", "./lib"], factory);
    }
})(function (require, exports) {
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    var lib_1 = require("./lib");
    var blah = "hello world";
    // console.log(blah);
    console.log(new lib_1.StringUtil(blah).upper());
});
//# sourceMappingURL=blah.js.map

我尝试按照一些 StackOverflow 帖子的建议删除模块参数,但它仍然输出与 commonjs 选项相同的内容。

切换到目标“es6”和模块“amd”,console.logs仍然在函数内,

{
    "compilerOptions": {
        "target": "es6",
        "module": "amd",
        "sourceMap": true,
        "watch": true
    }
}
define(["require", "exports", "./lib"], function (require, exports, lib_1) {
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    let blah = "hello world";
    // console.log(blah);
    console.log(new lib_1.StringUtil(blah).upper());
});
//# sourceMappingURL=blah.js.map

但是浏览器提示

Uncaught ReferenceError: define is not defined
    at blah.js:1

我读的越多,看到的相互矛盾的建议就越多,大多数帖子从未提及他们正在使用的 TypeScript 版本,所以我假设根据您的版本有不同的方法来执行操作?

tsc --version 说我使用的是 3.6.3

使 tsc blah.ts 输出我可以通过 index.html 中的脚本标记包含的内容的正确方法是什么?我没有使用 NodeJS,这只是一个静态 HTML 文件。在控制台中没有显示错误的“umd”也在使用导出,所以我想如果我设法以某种方式调用生成的匿名函数,它也会提示导出.

由于这将是一个执行基本 DOM 操作的小型应用程序,我如何让 tsc 将所有文件合并到一个 JS 文件中,这样我就没有 js 文件在运行时加载?或者是否可以通过脚本标签单独包含每个生成的 js 文件,执行类似的操作?

<script src="ts/lib.js"></script>
<script src="ts/blah.js"></script>

我不想使用任何额外的东西,我看到了很多关于 webpack、babel、gulp 等的帖子。这似乎让事情变得更加复杂。

其他一些 StackOverflow 帖子建议使用

tsc --out app.js blah.ts lib.ts --module

然后提示

Cannot compile modules using option 'out' unless the '--module' flag is 'amd' or 'system'.

所以我添加了“amd”模块标志:

tsc --out app.js blah.ts lib.ts --module amd

然后输出:

define("lib", ["require", "exports"], function (require, exports) {
    "use strict";
    exports.__esModule = true;
    var StringUtil = /** @class */ (function () {
        function StringUtil(input) {
            this.rawValue = input;
        }
        StringUtil.prototype.upper = function () {
            return this.rawValue.toUpperCase();
        };
        return StringUtil;
    }());
    exports.StringUtil = StringUtil;
});
define("blah", ["require", "exports", "lib"], function (require, exports, lib_1) {
    "use strict";
    exports.__esModule = true;
    var blah = "hello world";
    // console.log(blah);
    console.log(new lib_1.StringUtil(blah).upper());
});

通过脚本标签添加app.js

<script src="ts/app.js"></script>

浏览器控制台再次提示:

app.js:1 Uncaught ReferenceError: define is not defined
    at app.js:1

从“amd”切换到“system”,浏览器提示

app.js:1 Uncaught ReferenceError: System is not defined
    at app.js:1

除了浏览器控制台中的错误之外,我的 console.log 代码片段仍然位于一个我不知道如何调用的匿名函数中。

关于如何使用 TypeScript 实现如此简单的事情,有什么建议吗?

最佳答案

tsconfig.json 中使用 ES2015 作为 moduletarget 将其加载为:

<script src="ts/blah.js" type="module"></script>

编辑: 您可能会收到 404 not found 错误,因为根据今天(2020 年 1 月 18 日),javascript 模块功能需要使用文件扩展名完成导入。即:

import {myLib} from 'path/to/my/file.js' 

但是 javascript 不会发出 .js This is a know issue/feature request for Typescript regarding modules .

作为解决方法,您可以编写一个 npm 脚本来解析生成的 javascript 文件并修复扩展名,如 this Logger lib 中使用的扩展名。

关于javascript - 如何使用常规脚本标签运行模块 typescript 输出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59801793/

相关文章:

javascript - REGEX 在 javascript 中查找选项标签

javascript下拉菜单和flash冲突

javascript - Angular 2 : Check whether user's browser is compatible

Javascript/Typescript - 无法将所有内容映射到表格

javascript - 计算从绿色到红色的颜色值

javascript - 如何从 Protractor 中的输入元素获取文本值而不是 promise

javascript - 通过 javascript 将值传递给 php

javascript - Angular:如何从一个组件前端(app.component.html)到另一组件后端(other.component.ts)获取值

angular - DatePipe 没有提供者

javascript - express JS : Handlebars "each" tag not displaying content