# 機能設計書 65-型判定関数群

## 概要

本ドキュメントは、Vue 3の`@vue/shared`パッケージが提供する型判定関数群の設計仕様を記述する。`isString()`、`isFunction()`、`isObject()`、`isArray()`等のTypeScript型ガード関数を含み、Vue 3フレームワーク内部全体で使用される基盤ユーティリティである。

### 本機能の処理概要

型判定関数群は、JavaScriptの値の型を安全に判定するユーティリティ関数のコレクションである。TypeScriptの型ガード（type predicate）として定義されており、条件分岐の中で使用することで型の絞り込みが自動的に行われる。Vue 3のリアクティビティシステム、レンダラー、コンパイラ等、フレームワーク全体で広く使用される。

**業務上の目的・背景**：JavaScriptは動的型付け言語であり、ランタイム時の型判定が必要になるケースが多い。`typeof`演算子だけでは`null`がobjectと判定される等の問題があり、安全で一貫した型判定が必要である。また、TypeScript環境では型ガード関数を使用することで、コンパイラによる型推論を活用でき、型安全なコードを記述できる。`@vue/shared`パッケージに集約することで、Vue 3の各パッケージ間で統一された型判定ロジックを共有する。

**機能の利用シーン**：Vue 3フレームワーク内部のあらゆる場所で型に応じた分岐処理に使用される。外部開発者が直接使用することも可能。

**主要な処理内容**：
1. `isArray()`: Array.isArrayのエイリアス
2. `isMap()`: Mapインスタンス判定
3. `isSet()`: Setインスタンス判定
4. `isDate()`: Dateインスタンス判定
5. `isRegExp()`: RegExpインスタンス判定
6. `isFunction()`: 関数型判定（typeof === 'function'）
7. `isString()`: 文字列型判定（typeof === 'string'）
8. `isSymbol()`: Symbol型判定（typeof === 'symbol'）
9. `isObject()`: オブジェクト型判定（null除外、typeof === 'object'）
10. `isPromise()`: Promise判定（then/catchメソッドの存在チェック）
11. `isPlainObject()`: プレーンオブジェクト判定（Object.prototype.toString）
12. `toRawType()`: 内部型文字列取得（"[object Type]"から"Type"を抽出）
13. `toTypeString()`: Object.prototype.toString.call()
14. `objectToString`: Object.prototype.toStringのエイリアス
15. その他: `isOn()`, `isModelListener()`, `isIntegerKey()`, `isReservedProp()`, `isBuiltInDirective()`

**関連システム・外部連携**：Vue 3の全パッケージ（@vue/reactivity、@vue/runtime-core、@vue/runtime-dom、@vue/compiler-core、@vue/server-renderer等）から参照される。

**権限による制御**：特になし。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | フレームワーク内部ユーティリティ。直接的な画面関連なし |

## 機能種別

型判定ユーティリティ

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| val | `unknown` | Yes | 型判定対象の値 | 任意の値を受け付ける |

### 入力データソース

フレームワーク内部の各モジュールから直接呼び出される。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| isArray戻り値 | `val is any[]` | 配列であればtrue |
| isMap戻り値 | `val is Map<any, any>` | Mapであればtrue |
| isSet戻り値 | `val is Set<any>` | Setであればtrue |
| isDate戻り値 | `val is Date` | Dateであればtrue |
| isRegExp戻り値 | `val is RegExp` | RegExpであればtrue |
| isFunction戻り値 | `val is Function` | 関数であればtrue |
| isString戻り値 | `val is string` | 文字列であればtrue |
| isSymbol戻り値 | `val is symbol` | Symbolであればtrue |
| isObject戻り値 | `val is Record<any, any>` | オブジェクトであればtrue（null除外） |
| isPromise戻り値 | `val is Promise<T>` | Promiseであればtrue |
| isPlainObject戻り値 | `val is object` | プレーンオブジェクトであればtrue |
| toRawType戻り値 | `string` | 内部型名文字列（例: "Array", "Object"） |

### 出力先

呼び出し元への戻り値。

## 処理フロー

### 処理シーケンス

```
各関数は単純な1行の判定ロジック:

isArray = Array.isArray
isMap(val) = toTypeString(val) === '[object Map]'
isSet(val) = toTypeString(val) === '[object Set]'
isDate(val) = toTypeString(val) === '[object Date]'
isRegExp(val) = toTypeString(val) === '[object RegExp]'
isFunction(val) = typeof val === 'function'
isString(val) = typeof val === 'string'
isSymbol(val) = typeof val === 'symbol'
isObject(val) = val !== null && typeof val === 'object'
isPromise(val) = (isObject(val) || isFunction(val)) && isFunction(val.then) && isFunction(val.catch)
isPlainObject(val) = toTypeString(val) === '[object Object]'
toRawType(val) = toTypeString(val).slice(8, -1)
toTypeString(val) = Object.prototype.toString.call(val)
```

### フローチャート

```mermaid
flowchart TD
    A[型判定関数呼び出し] --> B{判定方法}
    B -->|typeof| C[isFunction/isString/isSymbol]
    B -->|Object.prototype.toString| D[isMap/isSet/isDate/isRegExp/isPlainObject]
    B -->|typeof + null check| E[isObject]
    B -->|duck typing| F[isPromise: then/catch存在チェック]
    B -->|Array.isArray| G[isArray]
    C --> H[boolean返却]
    D --> H
    E --> H
    F --> H
    G --> H
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-65-01 | null除外 | isObject()はnullをオブジェクトとして判定しない | isObject呼び出し時 |
| BR-65-02 | Promiseダックタイピング | isPromise()はthen/catchメソッドの存在でPromiseを判定する（instanceof不使用） | isPromise呼び出し時 |
| BR-65-03 | TypeScript型ガード | 全関数がTypeScriptの型ガード構文（val is Type）で定義される | TypeScript使用時 |
| BR-65-04 | イベントハンドラ判定 | isOn()はキー先頭が'on'で3文字目が大文字またはASCII範囲外の場合にtrueを返す | isOn呼び出し時 |
| BR-65-05 | 整数キー判定 | isIntegerKey()は'NaN'でなく、'-'で始まらず、parseInt結果と一致する文字列の場合にtrueを返す | isIntegerKey呼び出し時 |

### 計算ロジック

- `toRawType()`: `Object.prototype.toString.call(value)`の結果`"[object Type]"`から`slice(8, -1)`で`"Type"`を抽出する

## データベース操作仕様

該当なし。

## エラー処理

### エラーケース一覧

エラーは発生しない。すべての入力に対して安全にbooleanまたはstringを返す。

### リトライ仕様

該当なし。

## トランザクション仕様

該当なし。

## パフォーマンス要件

- `typeof`演算子を使用する関数（isString、isFunction、isSymbol）は非常に高速
- `Object.prototype.toString.call()`を使用する関数（isMap、isSet等）は`typeof`より若干遅いが、正確な型判定が可能
- `cacheStringFunction()`でキャメルケース/ハイフネート変換等の文字列操作関数をキャッシュし、同一入力の再計算を回避

## セキュリティ考慮事項

該当なし。型判定のみでセキュリティ影響はない。

## 備考

- `@vue/shared`パッケージはVue 3の全パッケージから参照される共有ユーティリティ
- `isPromise()`はinstanceofではなくダックタイピングで判定するため、ネイティブPromise以外のthenableオブジェクトもtrueと判定される
- `makeMap()`関数を使用して`isReservedProp()`と`isBuiltInDirective()`は事前計算済みのルックアップテーブルとして定義される

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: 基本的な型判定関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | general.ts | `packages/shared/src/general.ts` | isArray（39行目）、isMap（40-41行目）、isSet（42-43行目）: 基本コレクション型の判定 |
| 1-2 | general.ts | `packages/shared/src/general.ts` | isDate（45-46行目）、isRegExp（47-48行目）: 特殊オブジェクト型の判定 |
| 1-3 | general.ts | `packages/shared/src/general.ts` | isFunction（49-50行目）、isString（51行目）、isSymbol（52行目）: プリミティブ/関数型の判定 |
| 1-4 | general.ts | `packages/shared/src/general.ts` | isObject（53-54行目）: null除外のオブジェクト判定 |
| 1-5 | general.ts | `packages/shared/src/general.ts` | isPromise（56-62行目）: ダックタイピングによるPromise判定 |

**読解のコツ**: TypeScriptの型ガード構文`val is Type`に注目。これにより条件分岐後のブロックでvalの型が自動的に絞り込まれる。

#### Step 2: ユーティリティ関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | general.ts | `packages/shared/src/general.ts` | objectToString（64-65行目）、toTypeString（66-67行目）: Object.prototype.toStringの活用 |
| 2-2 | general.ts | `packages/shared/src/general.ts` | toRawType（69-72行目）: "[object Type]"から"Type"を抽出 |
| 2-3 | general.ts | `packages/shared/src/general.ts` | isPlainObject（74-75行目）: プレーンオブジェクト判定 |

#### Step 3: Vue固有の判定関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | general.ts | `packages/shared/src/general.ts` | isOn（15-19行目）: charCodeAtを使用した高速判定 |
| 3-2 | general.ts | `packages/shared/src/general.ts` | isModelListener（21-22行目）: 'onUpdate:'プレフィックスチェック |
| 3-3 | general.ts | `packages/shared/src/general.ts` | isIntegerKey（77-81行目）: 配列インデックスとしての有効性判定 |
| 3-4 | general.ts | `packages/shared/src/general.ts` | isReservedProp（83-89行目）: makeMap()による予約プロパティ判定 |
| 3-5 | general.ts | `packages/shared/src/general.ts` | isBuiltInDirective（91-94行目）: makeMap()による組み込みディレクティブ判定 |

#### Step 4: 文字列変換ユーティリティを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | general.ts | `packages/shared/src/general.ts` | cacheStringFunction（96-102行目）: 文字列変換関数のメモ化パターン |
| 4-2 | general.ts | `packages/shared/src/general.ts` | camelize（108-112行目）、hyphenate（118-120行目）、capitalize（125-128行目）: 命名規則変換 |
| 4-3 | general.ts | `packages/shared/src/general.ts` | hasChanged（143-144行目）: Object.isによるNaN対応の変更検出 |

### プログラム呼び出し階層図

```
@vue/shared/general.ts
    │
    ├─ 型判定関数（プリミティブ）
    │      ├─ isString(val)    → typeof val === 'string'
    │      ├─ isFunction(val)  → typeof val === 'function'
    │      ├─ isSymbol(val)    → typeof val === 'symbol'
    │      └─ isObject(val)    → val !== null && typeof val === 'object'
    │
    ├─ 型判定関数（Object.prototype.toString）
    │      ├─ toTypeString(val) → Object.prototype.toString.call(val)
    │      ├─ isMap(val)        → toTypeString === '[object Map]'
    │      ├─ isSet(val)        → toTypeString === '[object Set]'
    │      ├─ isDate(val)       → toTypeString === '[object Date]'
    │      ├─ isRegExp(val)     → toTypeString === '[object RegExp]'
    │      ├─ isPlainObject(val)→ toTypeString === '[object Object]'
    │      └─ toRawType(val)    → toTypeString.slice(8, -1)
    │
    ├─ 特殊判定関数
    │      ├─ isArray           → Array.isArray
    │      └─ isPromise(val)    → (isObject||isFunction) && isFunction(then) && isFunction(catch)
    │
    └─ Vue固有判定関数
           ├─ isOn(key)         → charCodeAt判定
           ├─ isModelListener(key) → startsWith('onUpdate:')
           ├─ isIntegerKey(key) → parseInt一致判定
           ├─ isReservedProp    → makeMap()
           └─ isBuiltInDirective→ makeMap()
```

### データフロー図

```
[入力]          [処理]                    [出力]

unknown val ──▶ 型判定関数 ──────────────▶ boolean (型ガード)
                   │
                   ├─ typeof演算子
                   ├─ Object.prototype.toString
                   ├─ Array.isArray
                   └─ ダックタイピング
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| general.ts | `packages/shared/src/general.ts` | ソース | 型判定関数群の定義 |
| makeMap.ts | `packages/shared/src/makeMap.ts` | ソース | makeMap()ユーティリティ（isReservedProp等で使用） |
| index.ts | `packages/shared/src/index.ts` | ソース | パッケージエクスポート |
