Tuntunan Praktis TypeScript - Bagian 1
Tags: typescript, indonesia
Published: 2023-07-19 04:03:00

Sebuah direktori dikatakan sebagai typescript (ts) _project_ jika ada file konfigurasi `tsconfig.json`.

_Default_ konfigurasi `tsconfig.json` (di-_generate_ dengan `tsc --init`) adalah sbb:

```
{
	"target": "es2016",
	"module": "commonjs",
	"strict": true,
	"esModuleInterop": true,
	"skipLibCheck": true,
	"forceConsistentCasingInFileNames": true
}
```

Referensi resmi `tsconfig.json` lengkap nya ada di https://www.typescriptlang.org/tsconfig atau bisa dilihat dengan `tsc --help --all`.

Jika kita jalankan compiler `tsc` (tanpa _options_ atau _arguments_) maka ia akan mencari file `tsconfig.json` pada direktori yang aktif saat ini, atau disemua parent direktori yang terdekat, lalu meng-compile sesuai konfigurasi yang diset.

Jika kita jalankan `tsc source.ts` (dengan argumen input source file), maka dia akan mengabaikan `tsconfig.json`, lalu meng-compile file `source.ts` menggunakan konfigurasi bawaan.

Atribut `target` bisa diisi dengan salah satu dari: `es3`, `es5`, `es6`/`es2015`, `es2016`, `es2017`, `es2018`, `es2019`, `es2020`, `es2021`, `es2022`, atau `esnext`. Atribut ini untuk menentukan versi JavaScript dari file output yang dihasilkan.

Atribut `module` untuk menentukan jenis modul yang akan dihasilkan, bisa diisi dengan salah satu dari: `none`, `commonjs`, `amd`, `umd`, `system`, `es6`/`es2015`, `es2020`, `es2022`, `esnext`, `node16`, `nodenext`.

Jika kita set `module` dengan `amd` atau `system`, kita bisa tentukan atribut `outFile` karena tipe modul ini akan mem-_bundle_ semua source file menjadi 1 file output. Untuk tipe modul yang lain, kita bisa set atribut `outDir` untuk menentukan di direktori mana hasil kompilasi akan dihasilkan.

Nilai _(value)_ dari atribut `module` dengan prefix "es" (yaitu es6, es2020, dan seterusnya) akan menghasilkan modul ES _(ESM)_ di `outDir`, sedangkan `commonjs`, `node16`, atau `nodenext` akan menghasilkan modul CommonJS _(CJS)_.

Catatan: nilai bawaan dari `outDir` adalah sama dengan direktori project. 

Catatan: Jika suatu paket npm (yaitu sebuah direktori dimana ada file `package.json`) adalah ESM (yaitu jika atribut `type` di package.json diset dengan `"module"`, bukan `"commonjs"`), maka file-file modul yang ada didalam nya tidak bisa menggunakan fungsi `require()`, tapi harus menggunakan deklarasi `import`.

Terkait kolaborasi antara esm dan cjs, ada atribut `esModuleInterop` untuk menentukan apakah output modul cjs yang dihasilkan bisa digunakan oleh modul esm.

Perhatikan contoh dibawah ini untuk menguji cjs yang dihasilkan bisa digunakan dalam konteks modul esm:

File sumber `./index.ts`:

```ts
export function isEven(x: number): boolean {
    return x % 2 === 0
}
```

Kompilasi menjadi modul cjs dengan:

```sh
$ npx tsc --outDir ./dist --module nodenext ./index.ts
```

`./dist/index.js` yang dihasilkan adalah sebagai berikut:

```js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isEven = void 0;
function isEven(x) {
    return x % 2 === 0;
}
exports.isEven = isEven;
```

Test modul cjs yang dihasilkan dengan cjs runtime:

```sh
$ node -e 'console.log(require("./dist"))'
```

Test modul cjs yang dihasilkan dengan esm runtime:

```sh
$ node --experimental-modules \
    -e 'import("./dist/index.js").then(console.log)'
```

Untuk melihat konfigurasi aktual dari suatu ts project yaitu dengan `tsc --showConfig`, output nya kurang lebih sbb:

```json
{
    "compilerOptions": {
        "target": "es2016",
        "module": "esnext",
        "esModuleInterop": true,
        "forceConsistentCasingInFileNames": true,
        "strict": true,
        "skipLibCheck": true
    },
    "files": [
        "./index.ts"
    ]
}
```

Perhatikan atribut `files` jika tidak kita set di `tsconfig.json` maka bawaannya adalah mencari semua file `.ts` yang ada di project direktori dan semua sub-direktori nya secara rekursif.

Kita bisa melihat file-file apa saja yang dibaca pada saat kompilasi dengan `tsc --listFilesOnlyshowFiles`.

Sebagai penutup bagian 1 ini, tinjau sesi shell berikut ini sebagai referensi singkat terkait hal-hal apa saja yang digunakan dalam artikel ini.

```sh
# buat direktori kerja sementara
$ mkdir /tmp/1 && cd /tmp/1

# inisialisasi npm project
$ pnpm init

# install ts 
$ pnpm install --save-dev typescript@latest 

# buat contoh source sederhana
$ cat <<EOF > index.ts
export function isEven(x: number): boolean {
    return x % 2 === 0
}
EOF

# inisialisasi tsconfig.json
$ npx tsc --init

# show aktual config
$ npx tsc --showConfig

# show aktual file-file yang digunakan selama proses kompilasi
$ npx tsc --listFilesOnly

# lakukan proses kompilasi
$ npx tsc --outDir ./dist

# test penggunaan modul hasil kompilasi nya
$ node -e 'console.log(require("./dist").isEven(2))'
$ node -e 'import("./dist/index.js").then(m => console.log(m.isEven(2)))'

# lihat pertolongan
$ npx tsc --help --all
```