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;
$ は不要です。代わりに let や const というキーワードを使います。
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 は書くことが増えると思うので、学習を続けていこうと思います。