0
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?

TypeScript vs Python vs Rust vs Ruby ── AIに20回コード書かせて分かった「本当の差」

0
Last updated at Posted at 2026-03-09

「AI にコード書かせるなら、結局どの言語がいいの?」

X でよく見るやつ:

「Python が一番安定する」
「TypeScript は型があるから有利」
「Rust はコンパイル通らなくて地獄」
「Ruby? 2026年にもなってまだ使ってるの?」

でも、実測データ付きの記事 が見当たらない。

みんな感想で語ってる。

ないなら作ろう。ということで──

Claude Opus 4.6 に同じ Todo API を 4言語×5回 = 計20回 書かせて、全部テストした。

結果は予想と全然違った。


なぜ「4言語×5回」なのか

AI のコード生成って、毎回ちょっと違うコードが出る

1回だけ試して「TypeScript 最強!」って言っても、たまたまかもしれない。だから5回ずつ回した。

選んだ4言語にも意図がある。

言語 なぜ選んだか
TypeScript 静的型付け × Web最大勢力。AI コード生成の「本命」
Python 動的型付け × AI/ML の母語。学習データ量なら最強
Rust 厳格コンパイラ。「AI には無理」って言われがち
Ruby 表現力特化。「オワコン」って言われがちだけど本当?

この4つで差が出ないなら、マジで「言語は関係ない」 と言い切れる。


検証方法:ズルできない仕組みにした

全体フロー

大事なのは 3つの「同一」

条件 やったこと
同一プロンプト 全言語に同じ PROMPT.md を渡す
同一テスト 全言語に同じ curl テスト(7項目)
同一AI Claude Code(Opus 4.6)で全20回

言語ごとにプロンプト変えたら、それは プロンプトの差 を測ってることになる。変数は 言語だけ

仕様:いわゆる「よくある Todo アプリ」

┌─────────────────────────────────────────┐
│  Todo REST API(1ファイル完結)            │
│                                         │
│  GET    /todos        → 一覧取得         │
│  POST   /todos        → 新規作成         │
│  PUT    /todos/:id    → 更新             │
│  DELETE /todos/:id    → 削除             │
│                                         │
│  DB: SQLite  /  Port: 8080              │
└─────────────────────────────────────────┘

AI コーディングの "Hello World" みたいなやつ。

これで差が出るなら、もっと複雑なタスクでは壊滅的な差になるはず。

テスト項目(7つ)

# 1. GET /todos        → 200 が返る
# 2. GET /todos        → 配列が返る
# 3. POST /todos       → 201 が返る
# 4. POST /todos       → title を含むオブジェクトが返る
# 5. POST → GET        → 作成済みアイテムが入っている
# 6. PUT /todos/1      → 更新内容が反映される
# 7. DELETE /todos/1   → 削除メッセージが返る

ステータスコードだけじゃなく レスポンスの中身まで検証 してる。「200返ったけど空っぽ」みたいな"なんちゃって成功"は通さない。


結果:全部動いた。煽りタイトルが死んだ。

正直に言う。

タイトルは 「動的型付けが最強だった」「Rust信者死亡確認」 で煽るつもりだった。

総合スコア

言語 テスト合格率 ビルド成功率 平均コード行数
TypeScript 100%(35/35) 100%(5/5) 115行
Python 100%(35/35) 100%(5/5) 122行
Rust 100%(35/35) 100%(5/5) 173行
Ruby 100%(35/35) 80%(4/5) 105行

全部100%。全部動いた。

20回連続でこれを見ることになった↓

=== Todo API Test Suite ===

  PASS: GET /todos returns 200
  PASS: GET /todos returns array
  PASS: POST /todos returns 201
  PASS: POST /todos returns todo with title
  PASS: GET /todos after POST has item
  PASS: PUT /todos/1 returns updated todo
  PASS: DELETE /todos/1 returns deleted message

===========================
Result: 7/7 passed, 0/7 failed

途中から感動より 退屈 のほうが勝った。

ちょっと待って、これすごくない?

2023年の GPT-4 や Claude 2 で同じことやったら、こうはならなかったと思う。

なんでこうなったのか。「AI が賢くなった」だけじゃない。

各言語のエコシステムが成熟して、パターンが固まった から。

「Express + SQLite ならこう書く」「FastAPI + SQLite ならこう書く」──こういうお手本コードがネット上に大量にある。AI はそのパターンを再現してるだけとも言える。

つまり:エコシステムが安定してる言語ほど、AI の生成精度が上がる。

これ、後で出てくる Ruby の失敗で裏付けられる。


でも「差がない」は嘘。体験は全然違う

テスト合格率は同じ。でも 使ってみた感覚 が全然違う。

ここからが本番。

Rust だけビルドに60秒かかる

言語 何が起きる 起動まで
TypeScript npm installtsx で実行 3秒
Python pip install → そのまま実行 3秒
Ruby bundle install → そのまま実行 5秒
Rust cargo build --release 65秒

20倍。Rust だけ20倍。

なにが問題かっていうと、AI Coding Agent の仕事って基本こういうループなんよ:

この 「ビルド」のところで毎回1分待つ ことになる。

人間がコーヒー入れに行く時間じゃない。Agent がただ待つ時間。しかも API 課金も発生しない。純粋に 何もしてない時間

今回は Todo アプリだから65秒で済んだけど、依存クレートが増えたら初回ビルドは 5〜10分 になったりする。その間に TS なら何回イテレーション回せるか……。

Rust が「遅い」のはランタイムじゃない。ビルドが。

誤解しないでほしいんだけど、「Rust 使うな」って話じゃない。フェーズを分けよう って話。

Rust だけコードが1.5倍長い

言語 Run-1 Run-2 Run-3 Run-4 Run-5 平均 振れ幅
Ruby 98 117 94 103 114 105 23行
TypeScript 131 114 128 114 92 115 39行
Python 134 131 119 114 114 122 20行
Rust 167 171 178 176 175 173 11行

なんで Rust だけ多いの? 型定義の義務 のせい。

同じ「Todo」を表現するのにこれだけ違う:

// Rust: 構造体が3つ必要(15行)
#[derive(Debug, Serialize, Deserialize)]
struct Todo {
    id: i64,
    title: String,
    completed: bool,
    created_at: String,
}

#[derive(Debug, Deserialize)]
struct CreateTodoRequest {
    title: String,
}

#[derive(Debug, Deserialize)]
struct UpdateTodoRequest {
    title: Option<String>,
    completed: Option<bool>,
}
# Ruby: 1行(型定義ゼロ)
params = JSON.parse(request.body.read)

Rust 15行 vs Ruby 1行。 AI が書いても人間が書いても、この差は消えない。

コード行数 = トークン消費量 だから、API 課金ベースだと Rust は 1.5倍のコスト

でもちょっと面白い発見がある。上の表の 「振れ幅」 を見てほしい。

Rust が一番安定してる。 振れ幅わずか11行。

型システムが厳格だから、書き方の自由度が低い。結果として AI の出力がほぼ同じパターンに収束する

冗長だけど安定。自由だけどブレる。面白いトレードオフ。

Ruby の「依存関係トラップ」

今回 唯一のビルド失敗 がこれ。Ruby の Run-1。

Sinatra could not start, the required gems weren't found!

Add them to your bundle with:

    bundle add rackup puma

Sinatra 4.x で rackup が別 gem に分離された。 AI がこの breaking change を知らなかった。

# Run-1(失敗)── rackup がない
gem 'sinatra'
gem 'sqlite3'
gem 'puma'

# Run-2以降(成功)── プロンプトで rackup を指定
gem 'sinatra'
gem 'sqlite3'
gem 'puma'
gem 'rackup'  # ← これ1行で全部解決

Ruby が悪いわけじゃない。AI の学習データの鮮度 の問題。

ただ、こういう差は出る:

AI にとって一番都合がいいのは「古いコードがそのまま動く」フレームワーク。

Express は10年以上 API が変わってないから、学習データがどの時期のものでも通用する。Sinatra は Ruby コミュニティの「前に進む」文化を反映して、大胆に依存を整理する。

後方互換性の高さが、AI 時代のフレームワーク選びの 新しい評価軸 になりそう。

教訓:AI にコード書かせるなら、フレームワークの最新バージョン情報をプロンプトに含めろ。


AI が選ぶフレームワーク、面白いくらい偏ってる

同じ仕様を投げても、言語ごとにまったく違うコード が出てくる。でもフレームワーク選択は完全に固定。

Hono? 選ばない。Flask? 選ばない。Axum? 選ばない。 全部「そのエコシステムで最もメジャーなやつ」一択。

TypeScript:Express + better-sqlite3

import express, { Request, Response } from "express";
import Database from "better-sqlite3";

const db = new Database("todos.db");
db.exec(`
  CREATE TABLE IF NOT EXISTS todos (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    title TEXT NOT NULL,
    completed INTEGER NOT NULL DEFAULT 0,
    created_at TEXT NOT NULL DEFAULT (datetime('now'))
  )
`);

const app = express();
app.use(express.json());

npm ダウンロード数で Express は月間3000万超。Fastify は300万、Hono は100万未満。AI は 「最もコード例が多いやつ」 を選ぶ。正確さを最大化する合理的な戦略。

Python:FastAPI(Flask は選ばれない時代に)

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import sqlite3, uvicorn

class CreateTodo(BaseModel):
    title: str

app = FastAPI()

5回とも FastAPI。一度も Flask は出てこなかった。 2026年の AI にとって Python Web API は「FastAPI がデフォルト」。

しかも面白いのが、動的型付け言語のはずの Python が Pydantic で事実上の型定義をやってる こと。Rust の構造体と似たアプローチだけど、バリデーション機能も兼ねてるから実用的。

Rust:actix-web + Mutex

use actix_web::{web, App, HttpServer, HttpResponse};
use rusqlite::Connection;
use std::sync::Mutex;

struct AppState {
    db: Mutex<Connection>,
}

5回とも actix-web。Axum は一度も選ばれなかった。 Axum は Tokio 公式なのに。

理由は単純で、actix-web のほうが歴史が長くて Stack Overflow のコード例が多いから。本番コードなら r2d2 でコネクションプールを使うべきだけど、Todo アプリなら Mutex で十分ではある。

Ruby:Sinatra のミニマリズム

require 'sinatra'
require 'sqlite3'
require 'json'

set :port, 8080
DB = SQLite3::Database.new('todos.db')
DB.results_as_hash = true

平均105行で最短。 型定義なし、設定最小限。Ruby の「書くべきコードが少ない」哲学が AI 生成でもそのまま出てる。

バリデーションなし、エラーハンドリングも最小限。良くも悪くも 「仕様通りに動くものを最短で」 が徹底されてる。


同じプロンプトなのに毎回コードが違う問題

地味だけど、これ結構大事な発見。

TypeScript の Run-1 と Run-2 を比較してみた:

ポイント Run-1 Run-2
DBパス path.join(__dirname, "todos.db") "todos.db"
WALモード あり なし
型定義 interface で別途定義 インライン
日時フォーマット datetime('now') strftime で ISO 8601
行数 131行 114行

どっちも正しい。でも設計判断が違う。

Run-1 は丁寧派。Run-2 は最小限派。AI は毎回サイコロを振って、ちょっとずつ違うアプローチを選んでる。

ただし アーキテクチャレベルでは安定(5回とも Express + better-sqlite3)。

               安定 ←──────────────→ 不安定

フレームワーク   ████████████████████  ほぼ固定
DB ライブラリ    ████████████████████  ほぼ固定
全体構造         ████████████████░░░░  だいたい同じ
細部の設計判断   ████████░░░░░░░░░░░░  毎回違う
コーディング規約 ██████░░░░░░░░░░░░░░  バラバラ

大きな方向性は同じだけど、細部がブレる。 これが AI コード生成の現在地。

チームで使うときどうする?

同じ仕様なのに、生成タイミングで WAL モードが入ったり入らなかったり。コードレビューのコストが上がる。

対策はシンプル:

皮肉なことに、AI コード生成の品質を上げるには 人間がより細かく設計判断を事前に決める必要がある。AI は「何を作るか」は分かるけど、「どう作るか」は毎回揺れる。


最終スコアカード

観点 TypeScript Python Rust Ruby
テスト合格率 ⭐⭐⭐ 100% ⭐⭐⭐ 100% ⭐⭐⭐ 100% ⭐⭐⭐ 100%
ビルド成功率 ⭐⭐⭐ 100% ⭐⭐⭐ 100% ⭐⭐⭐ 100% ⭐⭐ 80%
起動速度 ⭐⭐⭐ 3秒 ⭐⭐⭐ 3秒 ⭐ 65秒 ⭐⭐⭐ 5秒
コードの短さ ⭐⭐ 115行 ⭐⭐ 122行 ⭐ 173行 ⭐⭐⭐ 105行
依存の安定性 ⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐ ⭐⭐
生成の安定性 ⭐⭐ ⭐⭐ ⭐⭐⭐ ⭐⭐
総合 S S B+ A-

各言語を一言でまとめるとこう:

TypeScript  ──  万能。迷ったらこれ。
Python      ──  TS と互角。AI/ML やるなら最適。
Rust        ──  動くけど待つ。プロトタイプ向きではない。
Ruby        ──  最短最速。ただし依存関係に注意。

言語選択より大事だった3つのこと

20回回して気づいたんだけど、言語の違いより効いたのは別のところ だった。

1. プロンプトの精度 > 言語選択

Ruby が失敗したのは「Ruby だから」じゃなくて「プロンプトに rackup の指示がなかったから」。

プロンプト直したら Ruby も100%成功した。

言語を変えるよりプロンプトを直すほうが効果でかい。

2. テスト駆動が AI 時代にこそ効く

「全言語100%」って確認できたのは、先にテストを定義してたから

テストなかったら「動いてるっぽいけど PUT のレスポンスが仕様と違う」みたいなバグ、絶対見逃してた。

AI 時代の TDD。テストが「AI の品質保証」になる。

3. 「何を作りたいか」を言語化する力

AI は「Todo API 作って」で動くコードを返す。でも──

  • 「WAL モード使いたい」→ 言わないと入らない
  • 「ISO 8601 にしたい」→ 言わないと datetime('now') になる
  • 「バリデーション入れたい」→ 言わないと入らないことがある

設計意図は言わなきゃ反映されない。

AI 時代に磨くべきは「プログラミング言語の知識」じゃなくて 「何を作りたいか言語化する力」


再現方法

検証コードは GitHub で全部公開してます。

環境

項目 バージョン
macOS Darwin 24.3.0(Apple Silicon)
AI モデル Claude Opus 4.6
Node.js v22.16.0
Python 3.14.3
Rust 1.93.1
Ruby 4.0.1(Homebrew)

リポジトリ構成

benchmark/
├── spec/PROMPT.md          # 共通仕様書
├── test/test_api.sh        # 共通テスト(7項目)
├── run_benchmark.sh        # ベンチマークランナー
└── results/
    ├── typescript/run-{1-5}/  # 生成コード + result.json
    ├── python/run-{1-5}/
    ├── rust/run-{1-5}/
    └── ruby/run-{1-5}/

動かしてみる

# 1. クローン
git clone https://github.com/matsubara457/ai-coding-agent-benchmark.git
cd ai-coding-agent-benchmark

# 2. TypeScript run-1 を起動
cd benchmark/results/typescript/run-1
npm install
npx tsx app.ts
# → http://localhost:8080/todos

# 3. テスト(別ターミナル)
bash benchmark/test/test_api.sh
# → 7/7 passed が出るはず

まとめ

知見 一言
全言語100% 「この言語は AI と相性悪い」はもう通用しない
Rust はビルドが60秒 コードは正しい。待つのが辛い
Ruby は依存関係が罠 Sinatra 4.x の breaking change
コード量は Rust 1.5倍 型定義の宿命。トークンコストに直結
最短は Ruby 平均105行。ただし動かないリスク付き
鉄板は TS / Python 速い・安定・ちょうどいい
プロンプトが言語より効く 言語変えるより仕様を明確に

「AI にコード書かせるなら何の言語がいい?」

「何でもいい。もうそのレベルの議論は終わった。」

これが20回ベンチマーク回した人間の結論。

差がつくのは言語選択じゃなく、プロンプトの質仕様の明確さ

AI 時代に磨くべきスキルは「プログラミング言語の知識」じゃなくて「何を作りたいか言語化する力」だと、20回の実験で確信した。


検証コードは全部 GitHub に上げてあるので、ぜひ自分の環境で回してみてください。
違うモデルや仕様で試したら、きっと面白い結果が出るはず。

いいねとストックしてくれると次の検証のモチベになります。
面白い結果が出たら、コメントで教えてください。

0
0
0

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
0
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?