1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

eslint導入で警告だらけに!?日頃から気を付けたいTypeScript書き方まとめ

Last updated at Posted at 2025-11-30

はじめに

TypeScript + ESLint 環境を導入した瞬間、
「警告大量発生」「意味わからん赤線だらけ」
そんな経験、ありませんか?

この記事では、

  • eslint の推奨ルールに引っかかりがちな書き方
  • その改善方法

を 初心者にもわかりやすく まとめます。

1. ts-ignore を使わない(最後の手段)

NG

// @ts-ignore
const v = riskyValue;

OK

const v: unknown = riskyValue; // 明示的な型
// 型ガード
if (typeof v === 'string') {
  // ここから先は v が string だと推論される!
  console.log(v.toUpperCase());
} else {
  console.error('v is not a string:', v);
}

なぜ?

  • validate 無視はバグ温床

  • 修正ポイントがブラックボックス化

@ts-ignore は TypeScript が「あやしいぞ?」と警告してくれている部分を
強制的に黙らせる危険な指示です。なるべく使わないようにしましょう。

どうしても一時的に必要ならコメントを必ず併記します

// TODO: API型定義が更新され次第削除する
// @ts-ignore - ログデータのキーが動的なため
console.log(data["dynamic_key"]);

2. any を避ける(型は必ず定義する)

NG

let data: any;

OK

let data: unknown; // または具体的な型

なぜ?

  • any は型安全の恩恵が消える

  • 修正コストが後から爆増する

any はどのような値でも代入可能な型で、
any を使うと TypeScript の最大のメリット(型チェック)が完全に無効化されます。

それに対し、unknown型はどのような値でも代入可能な点は同じですが、
型チェックを行うため、下記のように型が保証されていないとメソッド呼び出しができません。

anyなら下記が通るが、

let value: any = "hello";
value.toFixed(2); // 実行時に落ちても TypeScript は止めない!

unknownでは通らない

let value: unknown = "hello";
value.toFixed(2); // ❌ コンパイルエラー(止めてくれる)
if (typeof value === "number") {
  value.toFixed(2); // ⭕ 安全
}
any unknown
何でも代入できる
何でも実行できる 〇(危険) ×(安全)
型チェックされるか × 完全スルー 〇 必須
バグ防止能力 低い 高い

3. 待たない非同期関数呼び出しの先頭に void をつける

非同期処理の結果が必要な際は、awaitしているので問題ないですが、結果を待たない場合も待たないことを明示する必要があります。

NG

asyncAction(); // eslint によく怒られる

OK

void asyncAction();

なぜ?

  • Promise が返っていることを明示できる

4. dot-notationルールが適用されないキーはブラケット記法(object["key"])を使用する

原則としてドット記法(object.key)が推奨されていますが、javascriptの識別子として無効なキー(予約語やハイフンなど)の場合に限り、ブラケット記法を使います。
逆にドット記法で記述できるものをブラケット記法で書くと警告が出るので気を付けてください。

こちらについては、そもそも構文エラーになります。
以下のような場合です。

NG

obj.default;

OK

obj["default"];

なぜ?

  • eslint(特に dot-notation) ルールで警告対象

  • JavaScript予約語・記号含むキーに対応

obj.key は一見シンプルで便利ですが
すべてのキーに使えるわけではない という落とし穴があります。

具体的には以下です。

エラー or 警告

obj.default;     // 予約語
obj.user-name;  // ハイフン入り
obj.日本語;     // 非推奨

すべてOK

obj["key_name"];
obj["default"];
obj["user-name"];
obj["日本語"];
ポイント
dot 記法は原則推奨
dot 記法で書けないキーは bracket 記法を使用
bracket 記法も型定義と合わせると安全
ESLint の dot-notation は bracket を必要に応じて指示

5. 未使用の変数は残さない

NG

const unusedVar = 123;

OK

const usedVar: number = 123;
console.log(usedVar);

なぜ?

  • 可読性・保守性が下がる

  • eslint が自動検出し怒られる代表例

6. == ではなく === を使う

NG

if (value == 0) {}

OK

if (value === 0) {}

なぜ?

  • 暗黙的な型変換でバグが生まれる
  • 意図が読み取り辛くなる
演算子 説明 特徴
== 等価演算(値だけ比較) 型が違っても自動で変換して比較する → 暗黙の型変換あり
=== 厳密等価演算(値 + 型比較) 型も値も同じ場合のみ true → 安全

暗黙型変換は言語によって異なり、意図しない挙動を起こしやすいので、多用しない方が良いです。
以前書いた記事を参考に置いておきます。
https://qiita.com/cho-tehu/items/2e099345a5081b2ef793

7. 変数宣言は var ではなく let / const

NG

var x = 1;

OK

const x: number = 1; // 書き換えない値は原則const

なぜ?

  • var はブロックスコープにならず予期せぬ動きを起こす可能性がある

var は昔の遺物なので、忘れてください。

var の問題点

  • 関数スコープ しか持たない
    → ブロック {} の中でも外で見えてしまう

  • 再宣言可能
    → 同じ変数名で上書きできてしまう

  • 巻き上げ(Hoisting) が発生
    → 宣言より前にアクセスできるように見える(バグの温床)

例えばこういうことができます。危険そうでしょ?

if (true) {
  var x = 10;
}
console.log(x); // 10 が出力されてしまう。ブロック外でも見える!

8. 未処理の例外をなくす (try/catch or .catch)

NG

fetchData(); // 結果がどうなるかわからない

OK

待たない非同期の時

void fetchData().catch(console.error);

待つ非同期の時

async function getData() {
  try {
    const data = await fetchData();
    console.log(data);
  } catch (err) {
    console.error(err);
  }
}

なぜ?

  • 例外未処理は意図しないシステム停止の危険性がある
  • eslint の no-floating-promises で警告対象

9. Union型は厳密に扱う

NG

function doSomething(v: string | number) {
  console.log(v.toUpperCase()); // numberの場合エラー
}

OK

if (typeof v === "string") {
  console.log(v.toUpperCase());
}

なぜ?

  • 型安全の基本

TypeScript の Union型(string | number など)は「複数の型のどれかが入る」という意味です。
型ごとにどういった処理を行うか、明確に記述しましょう。

複雑な場合はswitch文で扱うと、見やすいと思います。

switch (typeof v) {
  case "string":
    console.log(v.toUpperCase());
    break;
  case "number":
    console.log(v + 1);
    break;
}

まとめ

項目 理由
ts-ignore禁止 自爆装置
型を定義|anyを避ける バグを防ぐ
async呼び出しは void 先頭 意図を明示
object["key"] を使う 基本的にはドット記法を推奨
予約語・記号・動的キーでも安全にアクセス可能
未使用変数撤去 可読性up
=== を使用 暗黙変換回避
const 優先 予期せぬ再代入防止
try/catch徹底 安全な非同期
型ガード実施 union型健全化

最後に

開発が始まる前から導入しておき、最初からルールを強制するのがベストですが、
開発が進んでからeslintを導入し、大量に警告が出てしまうというケースは結構あると思います。
そういったとき、数千、数万件の警告が出るとげんなりして、eslintが敵に見えてきますが、eslint は 敵ではなく味方です。
警告はすべて「将来のバグ候補」なので、先に対処してしまった方が、総合的に見て開発コストが減るケースがほとんどだと思います。
チームでルールが強制されていなくても、自ら提案し、導入する。
それが無理な場合も多いと思うので、自分だけでも綺麗なコードを書いておき、自己防衛していきたいですね。

1
0
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?