👻

JavaScript/TypeScriptでプリミティブ型を理解する

に公開

はじめまして!
フロントエンドエンジニア志望の大学生です!

今回が初めての技術記事投稿になります。
まだ拙い部分もあるかと思いますが、JavaScript / TypeScript におけるプリミティブ型について、自分なりに整理して解説していきます。

はじめに

みなさんは、プログラミングで変数を使っているときに、「プリミティブ型とは何ですか?」と聞かれたら、すぐに説明できますか?

正直なところ、自分はまだうまく説明できませんでした。

「文字列や数値がプリミティブ型だ」ということは知っていても、実際にどんなものなのかを深く理解する機会はあまりありませんでした。

そこで今回は、プリミティブ型とは何かを自分なりに整理して解説していきたいと思います!

プリミティブ型とは?

プログラミング言語において、文字や数値などを扱うために、あらかじめ用意された基本的な型があります。これがプリミティブ型です。

JavaScript と TypeScript では、プリミティブ型には次の 7 種類があります。

  • string(文字列)
  • number(数値)
  • boolean(真偽値)
  • null(値が存在しないことを表す)
  • undefined(未定義を表す)
  • symbol(一意な識別子)
  • bigint(大きな整数)

プリミティブ型の特徴

プリミティブ型には、2つの特徴があります。

イミュータブル

1つ目の特徴は、イミュータブルであるということです。

イミュータブルとは、一度作成された値は変更できないという意味を表しています。

実際に、コードで見てみましょう!

let text = "hello";

// helloのhをHに直接書き換えようとしても…
text[0] = "H"; // ❌ できない

console.log(text); // "hello" のまま

"hello" という値は一度作られると変えられません。

変数textの中にある値を直接、変更できないという感じです。

数字の場合も見てみましょう!

let num = 42;

// 数値の一部を直接「書き換える」ことはできない
// 例えば十の位だけを 5 に変える、といった操作はできない

console.log(num); // 42 のまま

// 数値を変えるには、新しい値を再代入するしかない
num = 52;
console.log(num); // 52

このように、プリミティブ型は一度作成された値を、直接変更できない性質を持っています。
変数に新しい値を再代入することで、変数が指す値は変わりますが、元のプリミティブ値自体は変更されません。これがイミュータブル性の本質です。

基本的にメソッドやプロパティを持たない

2つ目の特徴は、基本的にプリミティブ型そのものにはメソッドやプロパティは存在しないことです。

しかし、JavaScript には オートボクシング という仕組みがあり、これによってプリミティブ型を一時的にオブジェクトのように扱えるようになります。

オートボクシングとは、null と undefined を除くプリミティブ型に対してオブジェクトのメソッドやプロパティにアクセスした際に、それぞれ対応するオブジェクトラッパー型(Boolean、Number、BigInt、String、Symbol)に一時的に変換してくれる仕組みです。

プリミティブ値にプロパティアクセスすると、自動的にオブジェクトラッパー型に変換され、そのメソッドやプロパティを使うことが出来ます。

ただし、null や undefined にアクセスすると TypeError になるため、オプショナルチェーン演算子などで安全に扱う必要があります。

詳しくは以下のサイトが参考に見てみてください!

よく使うプリミティブ型のJavaScript と TypeScript のコードの記述例

ここからは、よく使うプリミティブ型をJavaScript と TypeScript での書き方の違いを見ていきましょう。

string(文字列)

文字列は、テキストデータを表すためのプリミティブ型です。JavaScript でも TypeScript でも同じくプリミティブ型ですが、TypeScript では型注釈を付けることで安全に利用できる点が特徴です。

JavaScript の例

JavaScript では型の宣言がないため、代入する値によって自動的に文字列として扱われます。

// JavaScript の場合
let name = "Alice";            // 文字列

console.log(name.length);       // 5
console.log(name.toUpperCase()); // "ALICE"

// 文字列はイミュータブル(直接書き換え不可)
name[0] = "M";
console.log(name); // "Alice" のまま

JavaScript は動的型付け言語であるため、name に他の型を代入してもエラーは出ません。

TypeScript の例

TypeScript では型注釈を使って型を明示することで「これは文字列だ」と明示できます。

これにより 誤った代入 を防ぐことができます。

// TypeScript の場合
let name: string = "Alice";        // string 型を明示

console.log(name.length);          // 5
console.log(name.toLowerCase());   // "alice"

// number型の値を代入しようとするとエラー
// name = 100; // エラー: 型 'number' を型 'string' に割り当てることはできません

TypeScript では : string と型を指定することで、「文字列しか入らない変数」を保証でき、型安全性が高まります。


number(数値)

number は整数も小数もまとめて表す型です。

JavaScript では「数値型はひとつ」しかなく、TypeScript でも同じです

JavaScript の例

// JavaScript の場合
let age = 25;       // 整数
let pi = 3.14;      // 小数
let hex = 0xff;     // 16進数(255)

console.log(age + 5);     // 30
console.log(pi * 2);      // 6.28
console.log(hex);         //255

JavaScript では型がないため、文字列や他の型を代入してもエラーになりません。

TypeScript の例

// TypeScript の場合
let age: number = 25;      // number 型を指定
let pi: number = 3.14;

console.log(age + 5);      // 30
console.log(pi.toFixed(1)); // "3.1"

// ❌ 数字以外は代入できない
// age = "twenty";
// エラー: 型 'string' を型 'number' に割り当てることはできません

TypeScript では : number と書くことで「数値しか入らない変数」にできます。


boolean(真偽値)

boolean は true または false のみを表します。

条件分岐やフラグ管理に使われる、プログラミングで最も基本的な型のひとつです。

JavaScript の例

// JavaScript の場合
let isStudent = true;
let isAdmin = false;

console.log(isStudent);          // true
console.log(!isAdmin);           // true
console.log(Boolean(""));        // false
console.log(Boolean("hello"));   // true

truthy / falsy の判定があるため、空文字や 0 は false 扱いになります。

TypeScript の例

// TypeScript の場合
let isStudent: boolean = true;
let isAdmin: boolean = false;

console.log(isStudent && !isAdmin); // true

// ❌ 他の型を代入するとエラー
// isStudent = "yes";
// エラー: 型 'string' を型 'boolean' に割り当てることはできません

TypeScript では : boolean を指定することで、誤代入を防げます


null(値が存在しない)

null は「値が存在しないこと」を意図的に代入するための型です。

JavaScript の例

// JavaScript の場合
let empty = null;

console.log(empty);           // null
console.log(typeof empty);    // "object"(歴史的仕様)

null は「ここには何もない」と明示するときに使います。

TypeScript の例

// TypeScript の場合
let nickname: string | null = null;

if (nickname === null) {
  nickname = "Guest";
}

console.log(nickname); // "Guest"

TypeScript ではユニオン型を使い、string | null のように「値があるかもしれない/ないかもしれない」を表現できます。


undefined(未定義)

undefined は「変数が宣言されたが、値がまだ代入されていない」状態を表します。

また、存在しないオブジェクトのプロパティを参照したときも undefined になります。

JavaScript の例

// JavaScript の場合
let notAssigned;   // 値を入れていない
console.log(notAssigned); // undefined

const obj = {};
console.log(obj.missing); // undefined

undefined は「未設定」の意味合いで使われます。

TypeScript の例

// TypeScript の場合
let notAssigned: undefined; // 明示的に undefined 型

// ❌ string を代入するとエラー
// notAssigned = "hello";
// エラー: 型 'string' を型 'undefined' に割り当てることはできません

// null 合体演算子 ?? で安全に扱える
const title = undefined ?? "Untitled";
console.log(title); // "Untitled"

TypeScript では nullundefined を区別して扱えるため、安全なコードが書けます。

まとめ

  • プログラミング言語において、データを扱うためのあらかじめ用意された基本的な型
  • プリミティブ型は 7種類(string, number, boolean, null, undefined, symbol, bigint)
  • 特徴は 2つ
    • イミュータブル(値そのものは変えられない)
    • メソッドやプロパティを持たない(オートボクシングにより一時的にオブジェクト化される)
  • JavaScript では柔軟だが間違いに気づきにくい
  • TypeScript では型注釈を使うことで安全に利用できる

Discussion