Bagaimana cara menggunakan referensi proyek di TypeScript 3.0?


Ada fitur baru di TypeScript 3.0 yang disebut Project References. Ini menyarankan interaksi yang lebih baik dari modul *.ts di antara mereka sendiri.

Apakah ada yang bisa membantu saya memahami dengan tepat, masalah apa yang diselesaikannya, bagaimana caranya melakukannya, dan bagaimana saya akan mendapat manfaat darinya? Saya memiliki proyek dengan struktur yang serupa, jadi mungkin (atau mungkin tidak) sangat membantu untuk itu.

Struktur proyek kira-kira:

project/
    lib/
        index.ts # defines the original code
    test/
        index.spec.ts # requires lib/index.ts
    package.json
    tsconfig.json

Jawaban #1

Singkatnya:

Fitur ini memungkinkan mendefinisikan bagian-bagian dari proyek sebagai modul TypeScript yang terpisah. Di antara hal lainnya, ini memungkinkan mengonfigurasi modul-modul tersebut secara berbeda, membangunnya secara terpisah, dan sebagainya.


Sebelum

Awalnya, struktur proyek, ketika disederhanakan, mirip dengan ini:

/
    src/
        entity.ts # exports an entity
    test/
        entity.spec.ts # imports an entity
    tsconfig.json

Sebuah entitas didefinisikan dalam modul src/entity.ts, dan kemudian digunakan dalam file test/entity.spec.ts.

Perhatikan bahwa di sini hanya ada satu file tsconfig.json, yang berada di folder root. Ini pada dasarnya mengatakan bahwa folder ini berisi satu proyek TypeScript besar dan solid. Proyek ini mencakup beberapa file, yang diatur dalam folder; beberapa dari file tersebut digunakan untuk menguji file lainnya.

Namun, struktur ini menimbulkan masalah: proses kompilasi proyek (yaitu, tsc) juga mengompilasi berkas-berkas tes, sehingga membuat berkas dist/test/entity.spec.{js|d.ts} di output. Hal ini seharusnya tidak terjadi, oleh karena itu berkas tsconfig.json sedikit diubah untuk hanya menyertakan berkas/folder yang dimaksudkan untuk penggunaan di luar:

{
    "compilerOptions": {
        // compiler options
    },
    "include": [
        "./src"
    ]
}

Ini semacam menyelesaikan masalah, namun sekarang semua file di /test sama sekali tidak terkait dengan file di /src. Secara khusus, /test memiliki opsi kompiler sendiri; jadi, misalnya, mengatur strictNullCheck menjadi true di tsconfig.json akan menyebabkan kesalahan yang tidak konsisten, karena secara default nilainya false untuk file di /test.

Ini jelas sangat salah.


Setelah

Setelah menggunakan fitur ini, struktur proyek telah berubah menjadi seperti ini:

/
    src/
        entity.ts # exports an entity
        tsconfig.json
    test/
        entity.spec.ts # imports an entity
        tsconfig.json
    tsconfig-base.json

Mari kita melalui perubahan-perubahan ini:

  1. Mengganti nama /tsconfig.json menjadi /tsconfig-base.json adalah hal yang cukup besar itu sendiri: folder root tidak lagi menjadi proyek TypeScript, karena tsc mengharuskan file tsconfig.json untuk ada.
  2. Di sisi lain, menambahkan file src/tsconfig.json dan test/tsconfig.json mengubah src dan test menjadi dua proyek TypeScript yang terpisah, yang independen satu sama lain.

Isi dari file /{src|test}/tsconfig.json serupa karena tidak ada perubahan dalam konfigurasi yang diharapkan, yaitu, "strictness", folder output, serta parameter lainnya, harus dipertahankan. Untuk membuatnya serupa tanpa menyalin-tempel apa pun, semua konfigurasi dimasukkan ke dalam satu file sembarangan, yang dapat diakses dari kedua tempat; dalam hal ini, tsconfig-base.json di folder root dipilih untuk itu:

// the contents of /tsconfig-base.json
{
    "compilerOptions": {
        // compiler options, common to both projects
    }
}

File ini kemudian sedang "diwarisi" oleh file /{src|test}/tsconfig.json, dengan penambahan opsi lain jika diperlukan:

// the contents of /{src|test}/tsconfig.json
{
    "extends": "../tsconfig-base.json",
    "compilerOptions": {
        // additional compiler options, specific to a project
    }
}

Perhatikan bagaimana pola ini mirip dengan mendefinisikan sebuah kelas abstrak dengan implementasi yang tidak lengkap, dan kemudian memperluasnya dengan dua kelas "konkret" yang terpisah.

Sekarang, folder /src dan /test pada dasarnya menyimpan dua proyek TypeScript terpisah dengan konfigurasi yang serupa. Hal terakhir yang perlu dilakukan adalah menentukan hubungan antara keduanya. Karena test tergantung pada src, test harus entah bagaimana "mengetahui" tentang src. Ini dilakukan dalam dua langkah yang cukup jelas:

  • izinkan src untuk 'direferensikan' dari luar dengan menyatakannya sebagai 'komposit':

    // in /src/tsconfig.json
    {
        "extends": "../tsconfig-base.json",
        "compilerOptions": {
            // compiler options
            "composite": true
        }
    }
    
  • referensi src dari test:

    // in /test/tsconfig.json
    {
        "extends": "../tsconfig-base.json",
        "references": [
            { "path": "../src" }
        ]
    }
    

Array "include" di /tsconfig-base.json sekarang tidak diperlukan, karena pengecualian kode dilakukan dengan "menarik batas baru".

PEMBAHARUAN: bagian berikut tampaknya sudah usang sejak TypeScript 3.7

Sekarang, proyek test membutuhkan file *.d.ts untuk proyek src agar tersedia. Ini berarti sebelum menjalankan tes, src harus sudah dibangun sebelumnya, secara terpisah. Ini dilakukan dengan menggunakan mode baru dari tsc, yang diaktifkan oleh opsi --build:

tsc --build src

Perintah ini membangun proyek src dan menempatkan output di folder keluaran yang ditentukan (dalam hal ini, /dist), tanpa merusak test maupun kehilangan kesalahan kompilasi.

Jawaban #2

Ini untuk library TypeScript yang Anda kembangkan, yang digunakan oleh aplikasi TypeScript lain. Jadi misalnya, jika Anda membuat beberapa library util seperti lodash tetapi sedang mengembangkannya bersamaan dengan aplikasi yang tergantung padanya, references dalam ``tsconfig.json``` memungkinkan Anda mereferensikan kode sumber, dan membuat aplikasi yang tergantung itu dibangun ulang secara otomatis ketika sumber util berubah (yaitu: tsc mendeteksi perubahan kode sumber di library ts util)

Dalam kasus saya secara khusus, saya menggunakan references bersamaan dengan npm link dan submodules git dan ini bekerja jauh lebih baik dibandingkan pada masa ts 2.x.

Artikel terkait