2
1

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 入門:歴史、JavaScriptとの違い、便利機能

Posted at

対象: プログラミング初心者〜中級 / JavaScript経験者歓迎
ねらい: TypeScript(TS)が「なぜ生まれ」「何が便利で」「Javaなど名目型の言語とどう違うか」を、図とコード例で一気に理解


0) 結論(TL;DR)

  • TypeScript は 「大規模でも壊れにくい JavaScript を書くための、型とツールの拡張」
  • JS の上位互換なので、TS で書いたものは コンパイルして普通の JS になる(= 型は実行時に消える)
  • 構造的型付け(structural typing)により、“形(プロパティの集合)が同じなら互換”
  • エディタ補完・リファクタリング・API 変更検知など、実務の体験が劇的に良くなる

1) 歴史的経緯:TypeScript はなぜ生まれた?

2010年代、Webアプリが巨大化し、**型のない JS では“実行してみるまで壊れているか分からない”という悩みが増えました。
Microsoft は 2012 年に TypeScript を公開。
“アプリケーション規模の JavaScript 開発”を掲げ、静的型付けと強力な言語サービス(補完・ジャンプ・安全なリネーム)**を提供しました。以後も継続的に機能強化されています。

🔎用語メモ:静的型付け … 実行前(コンパイル時)に型の不整合を検出する仕組み。


2) JavaScript と TypeScript の根本的な違い

2-1. 「JS の上位互換」+ 型は実行時に消える(型消去)

TS は JS の上位互換(superset)。JS で書けるものは TS でも有効です。
TS の型注釈はコンパイル時のみ使われ、生成されるのは 普通の .js。実行時に型は存在しません。

// TypeScript
function add(a: number, b: number): number {
  return a + b;
}
// ↓コンパイル後(JavaScript): 型は消える
function add(a, b) { return a + b; }

2-2. **構造的型付け(structural typing)**が JS と相性抜群

TS の互換性は “形(プロパティの集合)で決まる” 方式。JS はオブジェクトの“形”を柔軟に扱う文化なので、実務で使いやすいです。

interface Pet { name: string }
class Dog { name = "Pochi" }
let p: Pet = new Dog(); // 形が同じなのでOK

2-3. 段階導入:既存 JS にも型チェックをかけられる

.jsにも JSDoc + // @ts-check で型チェック可能。少しずつ導入できます。

// @ts-check
/** @param {number} n */
function double(n) { return n * 2 } // 型エラーは編集時に通知

2-4. private と #private の違い(混同注意)

  • private(TSの修飾子) … コンパイル時チェックのみ
  • #private(ECMAScript私有フィールド) … 実行時に本当に隠蔽

3) TypeScript の“実務で効く”機能

3-1. 型注釈 & 型推論

注釈は 必要最小限でOK。TS はかなり賢く推論します。

const n = 42; // number と推論
const hello = "hello"; // "hello"(リテラル)または string と推論(文脈依存)

3-2. ユニオン / 交差型、ジェネリクス、interface / type

type Result = { ok: true; value: string } | { ok: false; error: Error };

function unwrap(r: Result): string {
  return r.ok ? r.value : r.error.message;
}

3-3. 制御フロー解析(narrowing)

条件分岐にもとづいて 変数の型を自動で絞り込み ます。

function lengthOf(x: string | string[]) {
  return typeof x === "string" ? x.length : x.length;
}

3-4. ユーティリティ型Partial / Pick / Omit / Record など)

既存型を 変形 するツール群。フォーム、API I/F などで大活躍します。

interface User { id: number; name: string; email: string }
type UserUpdate = Partial<User>;              // すべて任意プロパティに
type UserPreview = Pick<User, "name"|"email"> // 一部だけ取り出す

3-5. テンプレートリテラル型

文字列を型レベルで組み立て、キーのパターンを厳密に表現できます。

type Event = "user" | "order";
type Topic = `${Event}.created` | `${Event}.updated`; // "user.created" など

3-6. as constconst型パラメータ

  • as const … リテラルを きっちり固定
  • const型パラメータ … 関数側で 引数のリテラル性を保持
const palette = { primary: "blue", danger: "red" } as const;
// type: { readonly primary: "blue"; readonly danger: "red" }

function tuple<const T extends readonly unknown[]>(x: T) {
  return x; // T をそのまま保つ
}

3-7. satisfies 演算子

「このオブジェクトが型を満たすか」だけ検証し、推論は壊さない のがポイント。

type RGB = [number, number, number];
type Palette = Record<"red" | "green" | "blue", string | RGB>;

const p = {
  red: [255, 0, 0],
  green: "#0f0",
  blue: [0, 0, 255]
} satisfies Palette;

// p.red は [number, number, number] と推論される

3-8. デコレータ(標準仕様に追随)

クラスやメンバーに再利用可能な付加機能を付ける構文。ツールチェーンの対応状況も確認しつつ活用。

// 例(概念イメージ)
function log(target: any, key: string) { /* ... */ }

class Service {
  @log
  run() {}
}

3-9. 宣言ファイル(.d.ts)と型定義(@types

JS ライブラリに を付ける仕組み。npm i -D @types/ライブラリ名 で入手可能。

npm i -D @types/lodash

3-10. 巨大コードベース向け:Project References / 増分ビルド

プロジェクトを分割し、型チェックと再ビルドを高速化


4) Java など **名目型(Nominal Typing)**との違い

4-1. ざっくり対比

  • TypeScript:構造的型付け形(メンバー構成)が一致すれば代入OK
  • Java:名目型付け宣言上の関係(implements / extends)がないと代入NG

構造的(TS)

interface Pet { name: string }
class Dog { name = "Pochi" }
let p: Pet = new Dog(); // OK

名目型(Java)

interface Pet { String name(); }
class Dog { String name() { return "Pochi"; } }
// Pet p = new Dog(); // NG:Dog が Pet を implements していない

4-2. それぞれの実務的メリット/デメリット

観点 TS(構造的) Java(名目型)
柔軟性 “形が同じ”ならすぐ使える 関係を明示しないと使えない
API適合 オブジェクトリテラルでサクッと適合 型・継承関係を設計時に確定
安全性 うっかり互換が起こり得る 意図しない互換が起きにくい
読みやすさ “形”の把握が大変なことも 宣言に関係が現れ追いやすい

4-3. TS で“名目っぽく”するテク(ブランディング

同じ number でも USD と JPY を取り違えたくない … そんな時に ユニークシンボルでタグ付け します。

declare const USDBrand: unique symbol;
type USD = number & { readonly [USDBrand]: "USD" };

declare const JPYBrand: unique symbol;
type JPY = number & { readonly [JPYBrand]: "JPY" };

function pay(price: USD) {}
const priceUsd = 100 as USD;
const priceJpy = 100 as JPY;

pay(priceUsd); // OK
// pay(priceJpy); // コンパイルエラー:通貨の取り違えを防ぐ

5) 最初の一歩:導入レシピ(実務向け)

  1. 小さく試す:既存 .jsJSDoc + // @ts-check。よければ .ts へ移行。
  2. tsconfigstrict: true:厳しめに始め、必要に応じて例外を明示(// @ts-expect-error)。
  3. “必要十分な型” を心がける:過剰な注釈は書かず、推論・ユーティリティ型・satisfies を活用。
  4. 外部ライブラリは @types/* を確認:なければ最小の型宣言を足す。
  5. 大きくなったら分割Project References + 増分ビルドで体感速度アップ。

6) まとめ

  • ランタイム前にミスを潰せる安全にリファクタできる
  • JS の柔軟さを保ちつつ、構造的型付けでちょうど良い安全性。
  • 宣言ファイル・@types/*・エディタ連携など エコシステムが充実、段階導入もしやすい。

付録:用語ミニ辞典

  • 構造的型付け … **形(プロパティ/メソッドの集合)**が合えば同じ型とみなす(TS)。
  • 名目型付け名前・宣言で互換性を決める(Java/C#/…)。
  • 型消去 … 出力 JS から型情報が消える(TS の型は実行時に存在しない)。
  • narrowing(絞り込み) … 分岐などの 制御フロー解析で変数の型をより具体化。
  • ユーティリティ型Partial/Pick など 型操作の内蔵ツール
  • テンプレートリテラル型 … 文字列を 型レベルで合成 して表現力を高める。
2
1
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
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?