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

PHPエンジニアのためのTypeScript入門

1
Posted at

PHPエンジニアのためのTypeScript入門

PHP と TypeScript を比較しながら、JavaScript も交えて基本を解説します。
かなり初心者向けの記事となっております。

私自身、普段は PHP をメインで触っており JavaScript の知識自体も浅いのですが、TypeScript を学習の一環で触ってみたいと思いこの記事を書きました。
コード例は主に PHP と TypeScript の比較を中心に構成しています。JavaScript 固有の話題(非同期処理など)は適宜補足として触れています。


1. 変数・型の違い

PHP の変数

<?php
$name = "Alice";
$age  = 25;
$isActive = true;

PHP では変数に必ず $ を付けます。型は書かなくても動きます(動的型付け)。

JavaScript の変数

let name = "Alice";
let age  = 25;
let isActive = true;

$ は不要です。代わりに letconst というキーワードを使います。

TypeScript の変数(型付き)

let name: string = "Alice";
let age: number  = 25;
let isActive: boolean = true;

PHPで型を書くときは string $name(型→変数名の順)でしたが、TypeScriptでは name: string(変数名→型の順)と逆になります。これだけ覚えれば型注釈はOK。

PHP TypeScript
string $name name: string
int $age age: number
bool $isActive isActive: boolean
array $items items: string[] など

ポイント: TypeScript は型を省略しても、変数の初期値から型を自動で判断(推論)してくれます。let name = "Alice" と書くだけで string 型として固定され、後から name = 123 のように別の型を代入しようとするとエラーになります。PHPのように何でも入れ替えられる動的型付けとは異なります。


2. const をオブジェクトに使ったときの挙動

let と const の基本

JavaScript / TypeScript

let greeting = "Hello";
greeting = "Hi"; // OK:再代入できる

const appName = "MyApp";
appName = "OtherApp"; // エラー:再代入できない

const は「この変数に別の値を代入しない」という宣言です。

プリミティブ vs オブジェクトで挙動が変わる

ここが少しハマりポイントです。

プリミティブとは数値・文字列・真偽値など「それ以上分解できない単純な値」のことです。const をプリミティブに使うと完全に変更不可になりますが、オブジェクト({} で作るもの)に使うと中身のプロパティは変更できます。

JavaScript / TypeScript

const task = { id: 1, title: "買い物" };

// ❌ これはエラー:変数自体への再代入はNG
task = { id: 2, title: "掃除" };

// ✅ これはOK:プロパティの変更はできる
task.id = 3;
task.title = "料理";

const は「この箱(変数)に別の箱を入れ替えるな」という意味です。箱の中身を変えることは許可されています。

また task = { id: 2, title: "掃除" } のように丸ごと差し替えると、元々あった他のプロパティも消えてしまうという違いもあります。task.id = 3 のようにプロパティだけ変更すれば他は残ります。

PHP の define() との違い

<?php
define('APP_NAME', 'MyApp');
APP_NAME = 'Other'; // エラー(定数は変更不可)

// PHP で連想配列を define した場合(PHP 7.0+)
define('CONFIG', ['debug' => false]);
// 中身も変更できない

PHP の define() は中身まで完全に固定されますが、JavaScript/TypeScript の const はオブジェクト・配列の中身は変えられます。この違いは意識しておきましょう。


3. 関数の書き方

通常の関数定義

PHP

<?php
function greet(string $name): string {
    return "こんにちは、" . $name . "!";
}

TypeScript

function greet(name: string): string {
    return `こんにちは、${name}!`;
}

構造はほぼ同じです。function キーワード、引数、戻り値の型、処理内容。
文字列の埋め込みは PHP が "Hello " . $name なのに対し、TS はバッククォート ` で囲んで ${name} と書きます(テンプレートリテラル)。

アロー関数

JavaScript / TypeScript にはアロー関数という省略記法があります。

TypeScript

// 通常の関数
function add(a: number, b: number): number {
    return a + b;
}

// アロー関数(同じ意味)
const add = (a: number, b: number): number => {
    return a + b;
};

// 1行で書けるならさらに省略可能
const add = (a: number, b: number): number => a + b;

PHP 7.4 以降にも似た記法があります:

PHP

<?php
// PHP のアロー関数
$add = fn($a, $b) => $a + $b;

PHP のアロー関数は fn キーワードですが、TypeScript は => だけです。よく見るので慣れておきましょう。


4. オブジェクト・クラス

PHPはクラスが必須、TSは interface で型だけ定義できる

PHP でオブジェクト的なデータ構造を使うには、クラスを定義する必要があります。

<?php
class Task {
    public int $id;
    public string $title;
    public bool $done;

    public function __construct(int $id, string $title, bool $done) {
        $this->id    = $id;
        $this->title = $title;
        $this->done  = $done;
    }
}

$task = new Task(1, "買い物", false);

TypeScript では、型定義だけなら interface でシンプルに書けます。

// 型の定義だけ(実体はない)
interface Task {
    id: number;
    title: string;
    done: boolean;
}

// この型に合ったオブジェクトをそのまま作れる
const task: Task = { id: 1, title: "買い物", done: false };

interface はクラスのような「実装」を持たず、「このオブジェクトはこんな形をしているよ」という型の約束です。TypeScript/JavaScriptの世界では、クラスを使わなくてもオブジェクトをそのまま扱えます。

クラスが必要なときの比較

PHP

<?php
class TaskService {
    private array $tasks = [];

    public function add(string $title): void {
        $this->tasks[] = ['title' => $title, 'done' => false];
    }

    public function getAll(): array {
        return $this->tasks;
    }
}

$service = new TaskService();
$service->add("買い物");

TypeScript

class TaskService {
    private tasks: { title: string; done: boolean }[] = [];

    add(title: string): void {
        this.tasks.push({ title, done: false });
    }

    getAll(): { title: string; done: boolean }[] {
        return this.tasks;
    }
}

const service = new TaskService();
service.add("買い物");

クラスの書き方はかなり似ています。$this->this. になる点だけ意識すればOKです。


5. 非同期処理

PHPは基本「同期」、JS/TSは「非同期」が標準

PHPでコードを書くと、上から順番に1行ずつ実行されます(同期処理)。

PHP

<?php
$result = fetchFromDatabase(); // 終わるまで待つ
echo $result;                 // その後に実行

JavaScriptは元々ブラウザで動くため、「APIを呼んでいる間もUIを止めない」という非同期処理が得意です。

JavaScript(古い書き方)

// 古い書き方(コールバック)※見るだけでOK
fetch('/api/tasks', function(result) {
    console.log(result); // 取得できたら呼ばれる
});
console.log("ここが先に実行されることがある!");

async/await で PHP 風に書く

現代的な書き方では async/await を使って、PHPに近い感覚で書けます。

TypeScript

// async をつけた関数の中では await が使える
async function getTasks(): Promise<Task[]> {
    const response = await fetch('/api/tasks'); // 終わるまで待つ
    const tasks = await response.json();        // JSONを解析するのも待つ
    return tasks;
}

// 呼び出し側
async function main() {
    const tasks = await getTasks();
    console.log(tasks);
}

await を付けると「ここで待つ」という意味になり、PHPの同期的な書き方に近い感覚になります。

ポイント: async をつけた関数は自動的に Promise を返します。Promise は「いずれ結果が返ってくる約束」のようなものです。最初は「async/await を使えば大体PHPと同じように書ける」と覚えておけばOKです。


6. export とは何か

PHPのファイル読み込みとの違い

PHPでは require / include を使ってファイルを読み込みます。

<?php
// task.php
function createTask(string $title): array {
    return ['title' => $title, 'done' => false];
}
<?php
// main.php
require './task.php';
$task = createTask("買い物");

TypeScript(Node.js / モジュールシステム)では、使いたいものを明示的に export(公開)して、使う側が import(取り込む)します。

// task.ts
export interface Task {
    id: number;
    title: string;
    done: boolean;
}

export function createTask(title: string): Task {
    return { id: Date.now(), title, done: false };
}
// main.ts
import { Task, createTask } from './task';

const task: Task = createTask("買い物");
console.log(task);

PHPのアクセス修飾子との違い

PHP の public / private / protected はクラスの**メンバー(プロパティ・メソッド)**に対するアクセス制御です。

<?php
class User {
    public string $name;       // 外から見える
    private string $password;  // クラス外から見えない
}

一方、TypeScript の export はファイルレベルの公開・非公開のしくみです。

// 公開する(他のファイルから使える)
export function helperA() { ... }

// 公開しない(このファイル内だけで使える)
function helperB() { ... }

クラスのプロパティにも PHP と同様に public / private / protected が使えます:

class User {
    public name: string;
    private password: string;

    constructor(name: string, password: string) {
        this.name = name;
        this.password = password;
    }
}

まとめ:PHP → TypeScript 対応表

概念 PHP TypeScript
変数宣言 $name = "Alice" let name = "Alice"
定数(変更不可) define('X', 1) const x = 1
型注釈 string $name name: string
文字列埋め込み "Hello {$name}" `Hello ${name}`
関数定義 function foo(): void {} function foo(): void {}
アロー関数 fn($x) => $x * 2 (x) => x * 2
this $this-> this.
型定義(型だけ) ―(クラスが必要) interface Task { ... }
ファイル読み込み require './foo.php' import { foo } from './foo'
ファイル公開 ―(requireすれば使える) export function foo() {}
非同期処理 あまり使わない async/await が標準

おわりに

PHPとTypeScriptは思っているより共通点が多いです。

  • 変数・関数・クラスの概念はほぼ同じ
  • 型の書く順番が逆なだけ
  • const のオブジェクトの挙動だけ注意
  • 非同期は async/await で PHP 風に書ける

最初は「違う言語だから全部別物…」と感じるかもしれませんが、PHPの知識はしっかり活きます。
フロントを触る機会が増えると、必然的に TypeScript , JavaScript は書くことが増えると思うので、学習を続けていこうと思います。

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