コズイン/JS


KOTLIN/JSは、標準的なライブラリ、typesafetyとバニラJSで見つからない現代の機能の多くを提供する、JSの生態系にKotlin言語の完全な畏怖さをもたらします.
しかし、JSの生態系の最大の強みの一つは、あなたのために使用できるライブラリの大規模なコレクションです.Kotlin/JSはJSコードとの完全な相互結合を持っています、しかし、TSのように、それはJS API表面を記述するために外部宣言を要求します.Kotlinコンパイラをシャットダウンし、安全でない方法で進む方法があります.dynamic しかし、それは活字の言語としてkotlinの全体のポイントを打つ.
この記事を入力!ここでは、どのようにKOTLIN外部宣言をJSインポートにマップし、どのようにゼロから自分自身を書く方法をカバーします.うまくいけば道に沿っていくつかのヒントやトリックを学びます.

基礎


モジュールマッピング


あなたのKotlinコードをJSコードで素晴らしくするために、Kotlinexternal キーワード.注意external キーワードはトップレベル宣言でのみ必要であり、ネストされた宣言はexternal .
次の例を考えます.
@JsModule("module-name")               // 1
@JsNonModule                           // 2
external val myExternalModule: dynamic // 3
  • コンパイラがこの宣言がJSモジュールmodule-name
  • コンパイラがこの宣言がUMDリゾルバで動作できることを通知します.CommonJSを使用するときには必要ありません.
  • 宣言するexternal 値付きdynamic 種類これは、我々は現在我々のKotlinコードから使用できる外部JSコードへのReferenceです!dynamic タイプはエスケープハッチ、基本的にコンパイラは、この値の形は何でも(バニラJSのように)できることを伝える.そのタイプを後で安全にする方法を調べます.
  • エンティティマッピング


    これまでのところ、我々はトップレベルvalue 外部としてマークされますが、それは停止しません.コリン/JSサポートobject , class , interface , fun 外部スコープモデリングの入れ子宣言も.以下にJSとKOTLINエンティティの間の推奨されるマッピングを示します.
  • [ JS ]フィールドとプロパティget and set キーワード「コリン」val またはmutablevar
  • [ js ]関数とlambdafun メンバー関数val
  • JSclass -> 琴class
  • [ JS ]匿名オブジェクトの形状{} ) -> 琴interface
  • 上記の提案を念頭において、JSのこれらのすべてのエンティティがKotlinにどのように翻訳されるかを示します.
    class MyJSClass {
      myField
      constructor(initField = "69") {
        this.myField = initField
      }
      function myMethod(arg1 = 420) {
        return arg1 + 1
      }
      get myProperty() {
        return this.myField
      }
      set myProperty(value) {
        this.myField = value
      }
      get myImmutableProperty() {
        return this.myField
      }
    
      myLambda = () => ({ result: 1, answer: "42" })
    }
    
    external class MyJSClass(initField: String = definedExternally) {
      var myField: String
      fun myMethod(arg1: Int = definedExternally): Int
      var myProperty: String
      val myImmutableProperty: String
    
      interface MyLambdaReturn {
        var result: Int
        var answer: String
      }
      val myLambda: () -> MyLambdaReturn
    }
    
    特別な注意definedExternally 値.Kertlin宣言でハードコードを必要とせずに、JSで引数がデフォルト値を持っていることをコンパイラに伝えるのはきちんとした方法です.また、Kotlin(他の外部エンティティへの引数として渡す)で構築する計画の外部インターフェイスのオプションプロパティを宣言するために使用することもできます.このトリックにわずかな制限があります.
    external interface MyJSType {
      val optionalImmutableValue: String?
        get() = definedExternally
      var optionalMutableValue: String?
        get() = definedExternally
        set(value) = definedExternally
    }
    val myJsTypeInstance: MyJSType = object: MyJSType {
      // Now we only need to override properties we want to set
      override val optionalImmutableValue: String? = "noice"
    }
    

    NPMパッケージの宣言


    ほとんどの場合、NPMパッケージで動作する必要がありますpackage.json そして、単一のモジュールから深く入れ子になった再エクスポートを再エクスポートします.
    このようなパッケージを宣言するには、次の2つの戦略があります.object and file .
    両方を表示するには、このJSモジュールjs-greeter 例を参照してください.
    export const value = "69"
    export const anonymousObjectValue = {
      name: "John"
    }
    export class JSClass {
      static function initialise() {}
      memberValue = 420
    }
    export function defaultHello() {
      return "Default Hi"
    }
    export const helloLambda = (name = "Joe") => (`Hello ${name}`)
    export default defaultHello
    

    NPMパッケージオブジェクト


    外部のNPMパッケージのコンテナとしてオブジェクトを宣言するとき、そのオブジェクトはモジュール全体の役割を果たします.この戦略を使用する場合、ファイルは外部および正規のコテリン宣言の両方を混在させることができます.
    @JsModule("js-greeter")
    external object JSGreeter {
      val value: String
    
      object anonymousObjectValue {
        var name: String
      }
    
      class JSClass {
        companion object {
          fun initialise()
        }
        val memberValue: Number
      }
    
      fun defaultHello(): String
    
      fun helloLambda(name: String = definedExternally): String
    
      @JsName("default") // Overriding JS name mapping to `default` rather than `defaultExportedHello`
      fun defaultExportedHello(): String
    }
    

    パッケージファイル


    外部のNPMパッケージのコンテナとしてファイルを宣言するとき、そのファイルはモジュール全体の役割を果たし、そのファイルの中の宣言はJSモジュールファイルに1 : 1とマッチします.この戦略を使用する場合、ファイルは外部宣言のみを含むことができ、通常のKollinと外部宣言の混合は許可されません.最後に、すべての宣言がもはや入れ子になっていないのでexternal object また、その代わりにトップレベルの宣言であるexternal 個別に.
    @file:JsModule("js-greeter")
    
    external val value: String
    
    external object anonymousObjectValue {
      var name: String
    }
    
    external class JSClass {
      companion object {
        fun initialise()
      }
      val memberValue: Number
    }
    
    external fun defaultHello(): String
    
    external fun helloLambda(name: String = definedExternally): String
    
    @JsName("default") // Overriding JS name mapping to `default` rather than `defaultExportedHello`
    external fun defaultExportedHello(): String
    

    グローバルJS APIの宣言


    場合によっては、NPMから来ていないが、グローバルスコープ内のランタイムによって提供されるいくつかのJS APIにフックする必要があります.このような場合、必要なのは、モジュールの注釈のないプロジェクトのどこにでもAPIの形を宣言することです.ES 6ダイナミックインポートへのアクセス方法の例を示しますPromise タイプはKotlin標準ライブラリで提供されているWeb API宣言から来ます
    external fun import(module: String): Promise<dynamic>
    

    非JSモジュールの宣言


    JS開発は過去のJSのみのプロジェクトを発展させて、しばしば「非」JS資産を「輸入するために、いろいろなWebpackローダーを使います.これは、我々はJSモジュールをインポートするために使用された同じ戦略を介して同様にKotlin/JSで可能です.JSと同じように、適切なWebpackのローダを設定する必要があります.
    ここではいくつかのエキゾチックなJSインポートの例とそのコルトのそれらの等価物です.
    import CSS from "my-library/dist/css/index.css"
    import SCSS from "my-library/dist/scss/index.scss"
    import JsonModule from "my-library/package.json"
    
    @JsModule("my-library/dist/css/index.css")
    external val CSS: dynamic
    
    @JsModule("my-library/dist/scss/index.scss")
    external val SCSS: dynamic
    
    @JsModule("my-library/package.json")
    external val JsonModule: dynamic
    

    ダイナミック型を取り除く


    dynamic タイプは非常に便利で便利な外部API宣言チェーンを提携する場所で、それはKotlinが提供するすべてのタイプの安全性を破棄します.ケースのほとんどでは、あなたはexternal interface 代わりに.外部のインターフェイスは、モジュール宣言の中で入れ子にすることができますが、それは必須ではなく、コンパイル中に破棄され、実行時には存在しないため、プロジェクトのどこにでも住んでいます.
    @JsModule("my-library/package.json")
    external val packageJson: dynamic
    
    // === VS ===
    
    external interface PackageJson {
      val name: String
      val private: Boolean
      val bundledDependencies: Array<String>
    }
    
    @JsModule("my-library/package.json")
    external val typedPackageJson: PackageJson
    
    また、外部宣言の間に共通の特性を再利用するために使用することもできます.

    概要


    我々は、タイプの安全性を維持し、NPMライブラリの大規模な海のロックを解除するために外部JSコードにKollinコードをマッピングするときに私たちに利用可能なオプションの多くを見てきました.うまくいけば、あなたはここで役に立つ何かを見つけました.
    私が何かを逃したならば、コメントで知らせてください、そして、私はできるだけ完全にこの記事を作るためにそれを加えます.
    ハッピーコーディング!