TypeScript

#11
TIOBE#37
PYPL#9
GitHub#6
RedMonk#6
IEEESpectrum#5
JetBrains#6
プログラミング言語静的型付けJavaScriptWeb開発フロントエンドバックエンド

プログラミング言語

TypeScript

概要

TypeScriptは、Microsoftが開発したJavaScriptに静的型付けを追加したプログラミング言語です。

詳細

TypeScriptは2012年にMicrosoftによって開発された、JavaScriptのスーパーセットとして設計されたプログラミング言語です。JavaScriptのコードはそのままTypeScriptとして動作し、さらに静的型システム、インターフェース、ジェネリクス、デコレーターなどの機能を追加しています。TypeScriptコードはJavaScriptにトランスパイルされ、あらゆるJavaScript実行環境で動作します。大規模なアプリケーション開発における型安全性の向上、開発効率の向上、保守性の向上を目的としており、React、Angular、Vue.js、Node.jsプロジェクトで広く採用されています。

書き方の例

Hello World

// 基本的な出力
console.log("Hello, World!");

// 型注釈付きの変数
const message: string = "こんにちは、TypeScript!";
console.log(message);

// 関数の型注釈
function greet(name: string): string {
    return `Hello, ${name}!`;
}

console.log(greet("TypeScript"));

基本的な型システム

// プリミティブ型
let age: number = 25;
let name: string = "太郎";
let isActive: boolean = true;

// 配列
let numbers: number[] = [1, 2, 3, 4, 5];
let fruits: Array<string> = ["apple", "banana", "orange"];

// オブジェクト型
let person: { name: string; age: number } = {
    name: "田中太郎",
    age: 30
};

// Union型(複数の型を許可)
let id: string | number = "abc123";
id = 123; // これも有効

// リテラル型
let status: "success" | "error" | "loading" = "success";

インターフェース

// インターフェースの定義
interface User {
    id: number;
    name: string;
    email: string;
    age?: number; // オプショナルプロパティ
}

// インターフェースの使用
const user: User = {
    id: 1,
    name: "山田花子",
    email: "[email protected]"
};

// インターフェースの継承
interface Admin extends User {
    role: string;
    permissions: string[];
}

const admin: Admin = {
    id: 2,
    name: "管理者",
    email: "[email protected]",
    role: "administrator",
    permissions: ["read", "write", "delete"]
};

関数の型付け

// 関数の型注釈
function add(a: number, b: number): number {
    return a + b;
}

// アロー関数の型注釈
const multiply = (a: number, b: number): number => a * b;

// 関数型の変数
type MathOperation = (x: number, y: number) => number;

const divide: MathOperation = (a, b) => {
    if (b === 0) {
        throw new Error("Division by zero");
    }
    return a / b;
};

// オプション引数とデフォルト引数
function createUser(name: string, age?: number, role: string = "user"): User {
    return {
        id: Math.random(),
        name,
        email: `${name.toLowerCase()}@example.com`,
        age
    };
}

クラス

// クラスの定義
class Vehicle {
    protected make: string;
    protected model: string;
    private _mileage: number = 0;

    constructor(make: string, model: string) {
        this.make = make;
        this.model = model;
    }

    // ゲッター
    get mileage(): number {
        return this._mileage;
    }

    // メソッド
    drive(distance: number): void {
        this._mileage += distance;
        console.log(`${distance}km運転しました。総走行距離: ${this._mileage}km`);
    }

    getInfo(): string {
        return `${this.make} ${this.model}`;
    }
}

// 継承
class Car extends Vehicle {
    private doors: number;

    constructor(make: string, model: string, doors: number) {
        super(make, model);
        this.doors = doors;
    }

    getInfo(): string {
        return `${super.getInfo()} (${this.doors}ドア)`;
    }
}

const myCar = new Car("トヨタ", "プリウス", 4);
console.log(myCar.getInfo());

ジェネリクス

// ジェネリック関数
function identity<T>(arg: T): T {
    return arg;
}

const stringResult = identity<string>("hello");
const numberResult = identity<number>(42);

// ジェネリックインターフェース
interface Container<T> {
    value: T;
    getValue(): T;
}

class Box<T> implements Container<T> {
    constructor(public value: T) {}

    getValue(): T {
        return this.value;
    }
}

const stringBox = new Box<string>("TypeScript");
const numberBox = new Box<number>(123);

// 制約付きジェネリクス
interface Lengthwise {
    length: number;
}

function logLength<T extends Lengthwise>(arg: T): T {
    console.log(`長さ: ${arg.length}`);
    return arg;
}

logLength("文字列"); // OK
logLength([1, 2, 3]); // OK
// logLength(123); // エラー: numberにはlengthプロパティがない

型エイリアスと型ガード

// 型エイリアス
type StringOrNumber = string | number;
type UserRole = "admin" | "user" | "guest";

// 型ガード
function isString(value: StringOrNumber): value is string {
    return typeof value === "string";
}

function processValue(value: StringOrNumber): void {
    if (isString(value)) {
        // この中ではvalueはstring型として扱われる
        console.log(value.toUpperCase());
    } else {
        // この中ではvalueはnumber型として扱われる
        console.log(value.toFixed(2));
    }
}

// Discriminated Union
interface Circle {
    kind: "circle";
    radius: number;
}

interface Rectangle {
    kind: "rectangle";
    width: number;
    height: number;
}

type Shape = Circle | Rectangle;

function calculateArea(shape: Shape): number {
    switch (shape.kind) {
        case "circle":
            return Math.PI * shape.radius ** 2;
        case "rectangle":
            return shape.width * shape.height;
        default:
            // 網羅性チェック
            const _exhaustiveCheck: never = shape;
            return _exhaustiveCheck;
    }
}

デコレーター(実験的機能)

// クラスデコレーター
function sealed(constructor: Function) {
    Object.seal(constructor);
    Object.seal(constructor.prototype);
}

// メソッドデコレーター
function log(target: any, propertyName: string, descriptor: PropertyDescriptor) {
    const method = descriptor.value;
    
    descriptor.value = function (...args: any[]) {
        console.log(`${propertyName}メソッドが呼び出されました`);
        return method.apply(this, args);
    };
}

@sealed
class ExampleClass {
    @log
    greet(name: string): string {
        return `Hello, ${name}!`;
    }
}

バージョン

バージョン リリース日 主な新機能
TypeScript 5.5 2024-06 Inferred Type Predicates, Control Flow Narrowing
TypeScript 5.4 2024-03 NoInfer Utility Type, Object.groupBy support
TypeScript 5.3 2023-11 Import Attributes, Switch (true) Narrowing
TypeScript 5.2 2023-08 using Declarations and Explicit Resource Management
TypeScript 5.1 2023-06 Unrelated Types in Union, JSDoc @param and @returns
TypeScript 5.0 2023-03 Decorators, const Type Parameters
TypeScript 4.9 2022-11 satisfies Operator, Auto-Accessors

参考ページ

公式ドキュメント

学習リソース

開発ツール