https://github.com/kinjouj/chrome-extension-twifyをベースにTypeScriptビルド環境をメモ

TypeScriptをJavaScriptにトランスパイルする環境を作る

├── eslint.config.mjs
├── package.json
├── public
     └── manifest.json
├── src
     ├── app.ts
├── tsconfig.json
└── vite.config.js

TypeScriptをビルドするのに必要なのは

  • package.json
  • tsconfig.json
  • vite.config.js
infopublic/manifest.jsonはビルド時にビルド先にコピーされるので省略

src/app.ts

class Sample {
  say(): string {
    return 'Hello World';
  }
}

const sample: Sample = new Sample();
console.log(sample.say());

package.json

{
  "name": "test",
  "version": "0.0.1",
  "scripts": {
    "build": "vite build"
  },
  "devDependencies": {
    "@stylistic/eslint-plugin": "^5.2.3",
    "eslint": "^9.33.0",
    "typescript": "^5.9.2",
    "typescript-eslint": "^8.39.1",
    "vite": "^7.1.1"
  }
}

ビルドに必要な依存性とビルドスクリプトを定義するだけ

tsconfig.json

{
  "compilerOptions": {
    "target": "es2024",
    "module": "ESNext",
    "strict": true
  },
  "include": ["src/**/*.ts"]
}

必要最小限で。詳しくはhttps://www.typescriptlang.org/docs/handbook/tsconfig-json.html

vite.config.js

import { resolve } from 'node:path'
import { defineConfig } from 'vite'

export default defineConfig((opt) => {
  return {
    root: 'src',
    publicDir: "../public",
    build: {
      outDir: '../build',
      emptyOutDir: true,
      copyPublicDir: true,
      minify: false,
      rollupOptions: {
        input: {
          app: resolve(__dirname, 'src/app.ts'),
        },
        output: {
          entryFileNames: '[name].js',
        },
      },
    },
  }
});

publicディレクトリにあるファイルをbuild内にコピーしてsrc/app.tsをトランスパイルしたのをbuild/app.jsとしてビルドする

詳しいことはhttps://vite.dev/config/

ここまででビルドする環境自体はできたので

npm run build # or vite build

でビルドしてみるとbuild/app.jsは以下のようにトランスパイルされる

class Sample {
  say() {
    return "Hello World";
  }
}
const sample = new Sample();
console.log(sample.say());

これでビルドするだけな環境はおkってことで(ry

ESLintでLintできる環境を作る

npx eslint --init

でeslint.config.mjs(場合によって拡張子が異なる)が生成される。今回はtypescript-eslintの設定を利用するので以下のように修正

import eslint from '@eslint/js';
import globals from 'globals';
import stylistic from '@stylistic/eslint-plugin';
import tseslint from 'typescript-eslint';

export default tseslint.config(
  {
    files: ['**/*.{ts,tsx}'],
    extends: [
      eslint.configs.recommended,
      tseslint.configs.recommendedTypeChecked,
      tseslint.configs.stylisticTypeChecked,
    ],
    plugins: { '@stylistic': stylistic },
    languageOptions: {
      parserOptions: {
        projectService: true,
        tsconfigRootDir: import.meta.dirname,
      },
      globals: {
        ...globals.browser
      }
    },
    rules: {
      ...stylistic.configs.recommended.rules,
      ...tseslint.configs.recommended.rules,
      '@stylistic/semi': ['error', 'always'],
      '@typescript-eslint/array-type': 'error',
      '@typescript-eslint/consistent-type-imports': 'error',
      '@typescript-eslint/explicit-function-return-type': 'error',
      '@typescript-eslint/no-non-null-assertion': 'error',
    }
  },
  {
    ignores: ['**/*.js', '**/*.mjs']
  }
);

詳しくはhttps://eslint.org/docs/latest/use/configure/configuration-files

ちょっとわざとエラーを起こさせたいので先程のapp.tsを

say() {
    return "Hello World"
}

のように返り値の型の指定を削除してeslintを実行してみると

npx eslint

以下のようにエラーになる

> test@0.0.1 build
> npx eslint && vite build


/home/kinjouj/ts-sample/src/app.ts
  2:3  error  Missing return type on function  @typescript-eslint/explicit-function-return-type

✖ 1 problem (1 error, 0 warnings)

という感じでビルド前にLintでチェックしたりすることもできるようにする

以上終わり

余談

本番で使ったりするのであればもっと細かい設定とか色々必要なんだろうけどめんどくさいんで自分で調べろと

あとESLintのrulesとか色々設定しないと有効にならなかったりするのもあるんでそこが色々めんどくさいなって思ったりはした。 それとESLintはやたらと古い情報が多いので最近のFlat Config形式で書くみたいなのがあんまりなかったりとか あっても現在は使えなかったりとか色々あるんでそういう前方互換をあっさり壊していくJS界隈のスタイルは如何なものかとww