Angular 6打字稿与KotlinJs集成
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Angular 6打字稿与KotlinJs集成相关的知识,希望对你有一定的参考价值。
我刚刚设法在一个有角度的6个打字稿文件中导入Kotlin编译的javascript模块。这并不容易,结果让我感到困惑。我想知道是否存在更优雅的方式。
最初我带了一个Kotlin文件:
package com.example.test
data class SomeInterface(
var id: String? = null,
var value: String? = null
) {
}
它很好地编译为以下JavaScript
(function (root, factory) {
if (typeof define === 'function' && define.amd)
define(['exports', 'kotlin'], factory);
else if (typeof exports === 'object')
factory(module.exports, require('kotlin'));
else {
if (typeof kotlin === 'undefined') {
throw new Error("Error loading module 'TestKotlinCompiled'. Its dependency 'kotlin' was not found. Please, check whether 'kotlin' is loaded prior to 'TestKotlinCompiled'.");
}
root.TestKotlinCompiled = factory(typeof TestKotlinCompiled === 'undefined' ? {} : TestKotlinCompiled, kotlin);
}
}(this, function (_, Kotlin) {
'use strict';
var Kind_CLASS = Kotlin.Kind.CLASS;
function SomeInterface(id, value) {
if (id === void 0)
id = null;
if (value === void 0)
value = null;
this.id = id;
this.value = value;
}
SomeInterface.$metadata$ = {
kind: Kind_CLASS,
simpleName: 'SomeInterface',
interfaces: []
};
SomeInterface.prototype.component1 = function () {
return this.id;
};
SomeInterface.prototype.component2 = function () {
return this.value;
};
SomeInterface.prototype.copy_rkkr90$ = function (id, value) {
return new SomeInterface(id === void 0 ? this.id : id, value === void 0 ? this.value : value);
};
SomeInterface.prototype.toString = function () {
return 'SomeInterface(id=' + Kotlin.toString(this.id) + (', value=' + Kotlin.toString(this.value)) + ')';
};
SomeInterface.prototype.hashCode = function () {
var result = 0;
result = result * 31 + Kotlin.hashCode(this.id) | 0;
result = result * 31 + Kotlin.hashCode(this.value) | 0;
return result;
};
SomeInterface.prototype.equals = function (other) {
return this === other || (other !== null && (typeof other === 'object' && (Object.getPrototypeOf(this) === Object.getPrototypeOf(other) && (Kotlin.equals(this.id, other.id) && Kotlin.equals(this.value, other.value)))));
};
var package$com = _.com || (_.com = {});
var package$example = package$com.example || (package$com.example = {});
var package$test = package$example.test || (package$example.test = {});
package$test.SomeInterface = SomeInterface;
Kotlin.defineModule('TestKotlinCompiled', _);
return _;
}));
在package.json中,我将"kotlin": "^1.2.70",
添加到依赖项部分。在角度组件中,我必须使用这样的代码进行导入。
import * as TestKotlinCompiled from "../../generated/TestKotlinCompiled";
// @ts-ignore
const SomeInterface = TestKotlinCompiled.com.example.test.SomeInterface;
// @ts-ignore
type SomeInterface = TestKotlinCompiled.com.example.test.SomeInterface;
这是在SomeInterfac
模块生成的包com.example.test
中使用类TestKotlinCompiled
的最小强制性代码。
这里的问题如下。
qazxsw pmi是必需的,因为在编译时ts-compiler没有看到正在导入的模块的内容。
// @ts-ignore
是const
所必需的
new SomeInterface()
是type
所必需的
所有这些看起来非常黑客。我喜欢像没有let x: SomeInterface;
和import {SomeInterface} from '../../generated/TestKotlinCompiled' using namespace com.example.test
的const
更容易的东西。那么,有没有办法简化我的上述代码?
我成功地改善了Angular中KotlinJs的一点点可用性。我在type
处理我的实验
首先,我们必须在Gradle中创建一个多平台子模块。在那里我们生成js文件(以及其他可能的平台)。
然后我们添加到package.json ...
https://github.com/svok/kotlin-multiplatform-sample
proj-common是我们编译的Kotlin模块。那里的路径是kotlin-js文件的构建目的地。
因此,在打字稿中我们只使用一个npm模块
{
"dependencies": {
"kotlin": "^1.3.21",
"proj-common": "file:../build/javascript-compiled"
}
}
编译顺利,没有使用import {sample} from 'proj-common/proj-common';
// For class Sample
sample = new sample.Sample();
// For object Platform
platform = sample.Platform;
的必要性
更新
在上面的解释中存在子依赖性的问题。它们未被导出,但并非所有子依赖项都在npm存储库中具有等价物。以下代码解决了这个问题。
// @ts-ignore
然后,从前面的子模块导入:
tasks {
task<Sync>("assembleWeb") {
val dependencies = configurations.get("jsMainImplementation").map {
val file = it
val (tDir, tVer) = "^(.*)-([\d.]+-\w+|[\d.]+)\.jar$"
.toRegex()
.find(file.name)
?.groupValues
?.drop(1)
?: listOf("", "")
var jsFile: File? = null
copy {
from(zipTree(file.absolutePath), {
includeEmptyDirs = false
include { fileTreeElement ->
val path = fileTreeElement.path
val res = (path.endsWith(".js") || path.endsWith(".map"))
&& (path.startsWith("META-INF/resources/") || !path.startsWith("META-INF/"))
if (res && path.endsWith(".js") && ! path.endsWith(".meta.js")) jsFile = fileTreeElement.file
res
}
})
into("$npmTarget/$tDir")
}
jsFile?.also { packageJson(tDir, it, tVer) }
tDir to jsFile
}
.filter { it.second != null }
.map { it.first to it.second!! }
.toMap()
packageJson(npmDir, File(jsOutputFile), project.version.toString(), dependencies)
dependsOn("jsMainClasses")
}
assemble.get().dependsOn("assembleWeb")
}
fun packageJson(dir: String, jsFile: File, version: String, dependencies: Map<String, File> = emptyMap()) {
val deps = dependencies.map {
""""${js2Name(it.value)}": "file:../${it.key}""""
}.joinToString(",
")
val text = """
{
"name": "${js2Name(jsFile)}",
"version": "${version}",
"main": "./${jsFile.name}",
"dependencies": {
${deps}
}
}
""".trimIndent()
File("$npmTarget/$dir/package.json").apply {
if (parentFile.exists()) {
parentFile.delete()
}
parentFile.mkdirs()
writeText(text)
}
}
fun js2Name(jsFile: File) = jsFile.name.replace(""".js$""".toRegex(), "")
在typescript文件中:
{
"dependencies": {
"proj-common": "file:../build/npm"
}
}
示例项目见import {sample} from 'proj-common';
// For class Sample
sample = new sample.Sample();
// For object Platform
platform = sample.Platform;
更新2
现在,您可以使用kotlin common子项目创建完整的堆栈项目,就像在gradle中附加插件一样简单
https://github.com/svok/kotlin-multiplatform-sample
在编译期间,此插件将自动将所有kotlin-js jar包注入node_modules。
plugins {
id("com.crowdproj.plugins.jar2npm")
}
项目现在用这个插件重写。请参阅https://github.com/svok/kotlin-multiplatform-sample子模块。
以上是关于Angular 6打字稿与KotlinJs集成的主要内容,如果未能解决你的问题,请参考以下文章
将 CodeMirror 与 Angular2 集成(打字稿)
KotlinJS + Typescript:在 d.ts 文件中找不到 Atomicfu TraceBase 参考