Why not login to Qiita and try out its useful features?

We'll deliver articles that match you.

You can read useful information later.

15
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

TypeScriptの危険性

Posted at

はじめに

筆者は現在、ESMベースの素のJavaScriptにJSDocで型情報を付与し、tsc によって型定義(.d.ts)のみを出力する構成で開発を行っています。

この構成は、TypeScriptが提供する静的解析や補完といった恩恵は享受しつつ、

  • ビルドの煩雑さ
  • 型の複雑化
  • 言語的な矛盾
  • チーム運用コストの肥大化

といったTSの構造的な問題を回避する、極めてバランスの取れた開発スタイルであると思い採用しています。

本稿では、現在もTypeScriptを信仰的に使用している開発者・チームに対し、10の視点から冷静かつ厳密に問題提起をしていきます。

1. TypeScriptは「スーパーセット」であって「上位互換」ではない

TSを盲信している方々の言動を見ていると「TypeScriptはJavaScriptのスーパーセットである」という表現が、「上位互換」「より優れている」という誤解を招いているような気がしています。

実際には、

「JavaScriptの構文や動的特性に依存しながら、それを無理に静的型で包み込むという設計」

であり、「静的型付け言語のように見えるが調和していない」ように見えます

2. 型が「あること」と「信頼できること」は別

TypeScriptには、any, unknown, as, @ts-ignore といった型システムの抜け道が大量に存在します。
言語仕様を考えると不可避な機能ですが、これらを許容しながら「型があるから安心」と語るのは、論理的に破綻してします。

静的型はあくまで補助的な安全性であり、設計の不備や思考停止を防ぐものではありません。

3. TypeScriptの型システムは「後付け」であり、整合性に欠ける

JavaやSwiftのように、クラスベースで言語の設計段階から型を中心に組み上げられた静的型言語と異なり、TypeScriptはJavaScriptに後付けで型を適用するアプローチを取っていることを忘れてはいけません。

その結果として、

  • 実行時に型が存在しない(完全に消える)
  • 構造的型(Structural Typing)による曖昧な一致
  • 関数の返り値や構造が動的に変わる設計との乖離

が発生しやすく、型が保証するはずの「正しさ」が成立しづらいです

特に、「JSライクにTSを書いている」 のであれば、すぐに ESM + JSDoc の使用を検討した方が良いと思います。
Objectに対して動的に型の違うキーを追加し、利用者がどこから引っ張れば良いか分からないような型引数を指定しないと扱えないような実装を公開することがどれだけレベルの低いことか理解しておきましょう。

AWS Amplify さん、私はあなたの defineBackend() 関数とどう向き合えば良いのでしょうか?
Gen1で簡単にできたREST APIを追加する為のGen2の酷いドキュメントが こちら です。

amplify/backend.ts
import { defineBackend } from "@aws-amplify/backend";
import { Stack } from "aws-cdk-lib";
import {
  AuthorizationType,
  CognitoUserPoolsAuthorizer,
  Cors,
  LambdaIntegration,
  RestApi,
} from "aws-cdk-lib/aws-apigateway";
import { Policy, PolicyStatement } from "aws-cdk-lib/aws-iam";
import { myApiFunction } from "./functions/api-function/resource";
import { auth } from "./auth/resource";
import { data } from "./data/resource";

const backend = defineBackend({
  auth,
  data,
  myApiFunction,
});

// ..この後クソ長いCDKスタックを記述がある

これって普通に backend を引数にした createApi() 関数を api/resource.ts に定義して使えば api の定義をまとまられます。
普通はそうしますが出来ない理由がこれです。

const backend: Backend<{
    auth: ConstructFactory<BackendAuth>;
    data: ConstructFactory<AmplifyGraphqlApi>;
    myApiFunction: ConstructFactory<ResourceProvider<...> & ResourceAccessAcceptorFactory & AddEnvironmentFactory & StackProvider>;
}>

これが backend にカーソルを合わせると出てくるヒントですが、そもそもキーが動的で、type Backend@aws-amplify/backend から取り出せますが、その型引数はどこからどう引っ張れば取り出せるのか謎。

こう言う場合、createApi() 関数はこう書くしかありません。(CDKの内容なんて Backend<any> ではとても対応できません)

amplify/api/resource.ts
import {backend} from '../backend'

export function createApi() {
  //...
}

はい、普通は引数で入れるものを export / import で直接持っていきました。

もうTS終わってませんか? 頭大丈夫ですか?

そもそも論、AWSチームの AWS SDK も Amplify もどうして常に完全リニューアルしてしまうのでしょうか?
Amplify Gen2 に至っては、完全に作りかけのモック段階なのにどうしてAWSコンソールをGen2という全く別物の仕様に作り変えてしまうのでしょう?
信頼できるベンターとして論外ですし、普通にAWSを辞めるレベルの粗悪さです。

、、、話を戻しましょう。

4. 開発者の補完体験のために、プロジェクト全体が犠牲になっている

TypeScriptの最大の魅力は、補完、ジャンプ、インテリセンスといったIDE体験の向上ですね。

しかしその代償として、

  • 複雑な型設計
  • ビルドパイプラインの増加
  • 型定義の保守コスト

が発生しており、チーム全体の生産性や開発速度を確実に損なっていると思います

テメーが気持ちよくなるために、開発コストが倍増している現実は看過できません。
そう言う場合は家で一人でデュフっていて下さい。

5. 型のための型、ユーティリティのためのユーティリティという本末転倒

TypeScriptでは、型を再利用・合成するために、さらに抽象化されたユーティリティ型が必要になる。

これにより、

  • 実装とは直接関係のないコードが大量に生まれ
  • 読みづらく、壊れやすく、テスト不能な構造

がプロジェクト内に蔓延する。

「型を守るために実装が犠牲になる」ような状態は、本末転倒以外の何物でもない

Amplifyの例もこれに当てはまります。

6. 「TSがあればスケールする」という幻想

TypeScriptの導入理由としてよく挙げられるのが、「大規模開発に耐えられる」というものです。
まるでJavaでも使っているような言い方ですね。お笑いです。

確かに、型による静的検査は一定の安心材料になるります。
しかし、実際に大規模開発において求められるのは、

  • 明確な仕様と要件の定義
  • ドメイン駆動設計(DDD)やモジュール設計の力
  • テスト戦略の充実
  • 組織的なコードレビュー体制と運用ルール

といった、言語に依存しない設計と運用の実力です。


📌 さらに深刻な問題:TypeScriptがシステムを硬直化させることすらある

TypeScriptは型の整合性を強く求めるがゆえに、ある段階を超えると変更コストが異常に高くなる傾向があります。
3で言った、TSの言語仕様と型の不整合さも相まって、

  • 型の再設計が必要になる
  • 影響範囲が不明確になり、ビルドすら通らなくなる
  • 型定義が他のモジュールに波及し、修正が伝播する

その結果、

「型があるから安心してスケールできる」はずが、いつの間にか「型のせいで一切変更が効かない」状態に陥ることがあるはずです。

ここまで来ると、チームは「一部を書き直すより、リプレイスした方が早い」という選択を迫られます。
実際に、TypeScriptによって柔軟性を失ったコードベースが、長期的な保守困難性を生み、プロダクトの寿命を縮める例もあるようです

💡 スケーラビリティの鍵は型ではなく設計

つまり、TSはスケーラビリティの「保証」ではなく「条件の一部」に過ぎません。
むしろ導入と運用を誤れば、型という名の足かせになり得ることを知ってもらいたいです。

「スケールする開発」と「TypeScriptを使うこと」はイコールではない。
真のスケーラビリティは、設計力と運用体制に宿る。

7. tscの通過が安心材料になってしまう危険性

「tscが通っているから大丈夫」という認識は、開発チーム全体の思考停止を招く最悪の兆候であると思います。

実際には、

  • テストがない
  • 実行時の型保証がない
  • バリデーションが不十分

といった問題を覆い隠し、型だけで品質が担保されたかのような幻想を生みます
特に「型でバリデーションは出来ない」と言うことは覚えておいてほしいものです。

8. 柔軟性を捨ててまで得られるものが少ない

TypeScriptを導入することで、JavaScript本来の持つ柔軟性——すぐに書けて、すぐに試せて、すぐに変えられるという特性——は大きく損なわれます。

結果として、

  • 書けるはずのコードが「型的にNG」で書けない
  • 小さな修正にも型定義の修正が必要

といった事態が発生し、設計と変更に対するストレスが不自然に高くなります

9. 現場レベルでは高コスト構造になりやすい

TSは「正しく使えば」強力なツールであることは否定しません。
しかしそれには、

  • 適切な型設計の知識
  • 組織全体での合意形成
  • 一貫した設計ルール

といった極めて高度な運用が前提となります。(それこそJavaスタイルで書くような...)
中途半端な理解と運用では、むしろ開発速度と品質の両方が損なわれる可能性が高いでしょう。

TSを採用して得られるものとは一体何なのでしょうか?

10. ESM + JSDoc + tsc はTypeScriptの理想を抽出した形である

筆者が採用している ESM + JSDoc + tsc という構成は、

  • JSの柔軟性と実行速度を損なわず
  • 補完・型チェックの恩恵だけを享受でき
  • 型定義の配布(.d.ts)も可能

という点で、静的型付けの「良い部分」だけを抽出した理想的なアプローチなように思います。

TSの導入で苦しんでいるチームがあれば、この構成は非常に有効な代替手段となるはずです


結論:TypeScriptを採用する際は慎重な判断が必要

TypeScriptは、静的型付けによる補完や型チェックの恩恵を提供する一方で、運用や設計において多くの課題を抱えています。特に、以下の点を考慮せずに導入することは、プロジェクト全体の柔軟性や生産性を損なうリスクを伴います。

  1. 型の信頼性の限界
    TypeScriptの型システムは万能ではなく、any@ts-ignore といった抜け道が存在するため、型があることが必ずしも安全性を保証するわけではありません。

  2. 運用コストの増加
    型設計や保守にかかるコストが、プロジェクトの規模やチームのスキルセットに見合わない場合、かえって開発効率を低下させる可能性があります。

  3. 柔軟性の喪失
    JavaScript本来の持つ柔軟性が制約され、小さな変更にも型定義の修正が必要になるなど、開発のスピード感が失われることがあります。

  4. 設計力の重要性
    真にスケールする開発を実現するためには、言語に依存しない設計力や運用体制が不可欠であり、TypeScriptの導入がそれを補完するものではないことを認識する必要があります。

最後に

私のチームでは絶対に採用しませんが、TypeScriptを採用するかどうかは、プロジェクトの特性やチームの状況に応じて慎重に判断しましょう。
今回の問題提起で、今一度 TypeScript について見直して頂けますと幸いです。

15
13
2

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

@MadakaHeri's pickup articles

MadakaHeri

@MadakaHeri(ヘリ マダカ)

Web系エンジニア。AWS / Laravel / Vue.js
Linked from these articles

Comments

icecake
@icecake
(Edited)

TypeScriptについていろいろ批判されてますが、正直その批判ってほとんどが使い方や設定次第で解決できることばかりだと思います。
ちょっと反論させてください。

1. 型の複雑さの話

結局それってプロジェクト設計とかチームの経験次第なんですよね。ちゃんと使えば型定義のおかげでコードが分かりやすくなったり、ミスが減ったりします。つまり、コードが読みやすくてメンテも楽になるってことです。

いつの間にか「型のせいで一切変更が効かない」状態に陥ることがあるはずです。
ここまで来ると、チームは「一部を書き直すより、リプレイスした方が早い」という選択を迫られます。

あなたの勤めておられる会社ではあるのかもしれませんが、例えばオープンソースなどで型が難しくなったのでリプレースします!って聞いたことあります?
お腹抱えて笑っちゃうレベルですよ。

2. コンパイルが遅いって話

たしかに、大きなプロジェクトだとコンパイル速度は気になるかもしれません。でも最近のTypeScriptはどんどん改善されていて、差分コンパイルとかインクリメンタルビルドを使えばかなり高速になります。Viteなどちゃんと設定すれば、そこまでストレスにならないです。

3. JavaScriptとの互換性

JavaScriptとの互換性が問題視されてますけど、実際のところほとんど問題になりません。むしろTypeScriptってJavaScriptとの互換性めちゃくちゃ高いし、徐々に移行するのも簡単です。型があるおかげで早めにバグを見つけられて、開発速度が上がることがほとんどだと思います。

4. ライブラリの型定義が微妙な問題

たしかに一部ライブラリの型定義がイマイチなこともありますが、コミュニティがすごく活発なので、どんどん改善されてます。それに、最悪自分で型定義書けば済む話です。最近はライブラリ自体がTypeScriptで提供されることも多くなってるから、この問題も減ってきてますよ。

5. 学習コストが高いって話

TypeScriptを覚えるのに最初はちょっと時間がかかりますが、それは型を使った開発自体のスキルアップにも繋がるし、長い目で見るとメリットのほうが大きいです。一度覚えれば、バグが減ってコードが読みやすくなって、結局効率が上がります。

6.「TSがあればスケールする」という幻想

そんな奴いねーわ。
それは TypeScript の問題ではなくあなたの周りにバカしかいないんじゃないですか。

結論

というわけで、批判点の多くは使い方次第で解決できますし、TypeScriptそのものの問題とは言えないかなと思います。ちゃんと使えば圧倒的にメリットのほうが大きいので、フロントエンドもバックエンドもTypeScriptを採用する価値は十分あります。

TypeScriptを嫌ってる暇があるなら、さっさと型を書いてバグを減らしましょう!

追記)
もしあなたに部下がいるなら部下の将来のキャリアアップのためにも ESM + JSDoc + tsc なんて主流じゃないわけわからないことをやってないで TypeScript をやらせてあげてください。

React、Angular、Next.js、NestJS、Ant Design、Stencil、Ionic、Chakra UI、Playwright、Zustandなどなど TypeScript で書かれていますが成功しています。

ESM + JSDoc + tsc で書かれて成功しているライブラリを教えてください。

2
MadakaHeri
@MadakaHeri(ヘリ マダカ)

@icecake 本質的な部分の回答が抜けてますね。
TSは型のために無駄なコード、本質的では無い書き方を強要してきます。
その積み重ねがリプレイスに繋がる訳です。
TSの場合、型が安全とも言えないのは本稿にも書いてある通りで、元が動的型付けな言語に型を付けたところで不整合が起きやすいんですよ。
あとAWSは毎回リプレイスしてきますし、そもそもnpmパッケージ界隈は破壊変更を簡単にし過ぎる。

そもそもTSの現場でそんな「出来るエンジニア」ばかり集められてるチームってあるんでしょうか?無いでしょ、日本の仕組み的にもアメリカのように「ダメだったら解雇」って出来ないんですよ。新人が入ったら全部コードレビューしてOK出るまでマージしないのは出来ますが、それをどれだけ継続出来ますか?
そう言う条件の中でTSを使うメリットが果たしてどれだけあるんでしょうか?
私は無いと思いますし、皆がESMを軽視してTSに乗り換えていくことに危機感を感じたのでこの記事を書きました。

0

Let's comment your feelings that are more than good

Qiita Conference 2025 will be held!: 4/23(wed) - 4/25(Fri)

Qiita Conference is the largest tech conference in Qiita!

Keynote Speaker

ymrl、Masanobu Naruse, Takeshi Kano, Junichi Ito, uhyo, Hiroshi Tokumaru, MinoDriven, Minorun, Hiroyuki Sakuraba, tenntenn, drken, konifar

View event details

Being held Article posting campaign

15
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Login to continue?

Login or Sign up with social account

Login or Sign up with your email address