--- paths: - "**/*.ets" - "**/*.ts" - "**/module.json5" - "**/oh-package.json5" - "**/build-profile.json5" --- # HarmonyOS / ArkTS コーディングスタイル > このファイルは [common/coding-style.md](../common/coding-style.md) を HarmonyOS および ArkTS 固有のコンテンツで拡張します。 ## ArkTS 言語の制約 ArkTS は TypeScript の厳格な静的型付きサブセットです。これらの制約に違反すると**コンパイルエラー**が発生します。 ### 型システム - `any` や `unknown` 型は使用不可 — 常に明示的な型を使用する - インデックスアクセス型は使用不可 — 型名を直接使用する - 条件付き型エイリアスや `infer` キーワードは使用不可 - 交差型は使用不可 — 継承を使用する - マップ型は使用不可 — クラスと通常のイディオムを使用する - 型注釈に `typeof` は使用不可 — 明示的な型宣言を使用する - `as const` アサーションは使用不可 — 明示的な型注釈を使用する - 構造的型付けは使用不可 — 継承、インターフェース、型エイリアスを使用する - `Partial`、`Required`、`Readonly`、`Record` 以外の TypeScript ユーティリティ型は使用不可 - `Record` のインデックス式の型は `V | undefined` - `catch` 句では型注釈を省略する(ArkTS は `any`/`unknown` をサポートしない) ### 関数とクラス - 関数式は使用不可 — アロー関数を使用する - ネストした関数は使用不可 — ラムダを使用する - ジェネレーター関数は使用不可 — マルチタスクには `async`/`await` を使用する - `Function.apply`、`Function.call`、`Function.bind` は使用不可 — `this` には従来の OOP を使用する - コンストラクタ型式は使用不可 — ラムダを使用する - インターフェースやオブジェクト型のコンストラクタシグネチャは使用不可 — メソッドかクラスを使用する - コンストラクタ内でのクラスフィールド宣言は不可 — クラス本体で宣言する - スタンドアロン関数や静的メソッドで `this` は使用不可 — インスタンスメソッド内のみ - `new.target` は使用不可 - 確実な代入アサーション(`let v!: T`)は使用不可 — 初期化済み宣言を使用する - クラスリテラルは使用不可 — 名前付きクラス型を導入する - クラスをオブジェクトとして使用(変数への代入)は不可 — クラス宣言は値ではなく型を導入する - クラスごとに静的ブロックは1つのみ — すべての静的ステートメントをまとめる ### オブジェクトとプロパティアクセス - 動的フィールド宣言や `obj["field"]` アクセスは使用不可 — `obj.field` 構文を使用する - `delete` 演算子は使用不可 — 不在を示すには `null` を持つ nullable 型を使用する - プロトタイプへの代入は使用不可 — クラスとインターフェースを使用する - `in` 演算子は使用不可 — `instanceof` を使用する - オブジェクトメソッドの再代入は不可 — ラッパー関数や継承を使用する - `Symbol()` API は使用不可(`Symbol.iterator` を除く) - `globalThis` やグローバルスコープは使用不可 — 明示的なモジュールのエクスポート/インポートを使用する - 名前空間をオブジェクトとして使用は不可 — クラスかモジュールを使用する - 名前空間内のステートメントは不可 — 関数を使用する ### 分割代入とスプレッド - 分割代入や変数宣言は使用不可 — 中間オブジェクトとフィールドごとのアクセスを使用する - 分割代入のパラメータ宣言は使用不可 — パラメータを直接渡し、ローカル名を手動で割り当てる - スプレッド演算子は配列(または配列派生クラス)をレストパラメータや配列リテラルに展開する場合のみ使用可 ### モジュールとインポート - `require()` は使用不可 — 通常の `import` 構文を使用する - `export = ...` は使用不可 — 通常のエクスポート/インポートを使用する - インポートアサーションは使用不可 — ArkTS ではインポートはコンパイル時に解決される - UMD モジュールは使用不可 - モジュール名にワイルドカードは使用不可 - すべての `import` ステートメントは他のすべてのステートメントより前に記述する - TypeScript のコードベースは import 経由で ArkTS のコードベースに依存してはならない(逆はサポート) ### その他の制限 - `var` は使用不可 — `let` を使用する - `for...in` ループは使用不可 — 配列には通常の `for` ループを使用する - `with` ステートメントは使用不可 - JSX 式は使用不可 - `#` プライベート識別子は使用不可 — `private` キーワードを使用する - 宣言のマージ(クラス、インターフェース、列挙型)は不可 — 定義をコンパクトに保つ - インデックスシグネチャは使用不可 — 配列を使用する - カンマ演算子は `for` ループ内のみ - 単項演算子 `+`、`-`、`~` は数値型のみ(暗黙の文字列変換なし) - 列挙型のメンバー: 明示的な初期化子には同じ型のコンパイル時式のみ - 関数の戻り値型推論は制限あり — 戻り値型を省略した関数呼び出し時は明示的に指定する ### オブジェクトリテラル - コンパイラが対応するクラスやインターフェースを推論できる場合のみサポート - 次の場合はサポートされない: `any`/`Object`/`object` 型、メソッドを持つクラス/インターフェース、パラメータ付きコンストラクタを持つクラス、`readonly` フィールドを持つクラス ## 命名規則 - 変数 / 関数: `camelCase`(例: `getUserInfo`、`goodsList`) - クラス / インターフェース: `PascalCase`(例: `UserViewModel`、`IGoodsModel`) - 定数: `UPPER_SNAKE_CASE`(例: `MAX_PAGE_SIZE`、`COLOR_PRIMARY`) - ファイル名: コンポーネントは `PascalCase`(例: `HomePage.ets`)、ユーティリティは `camelCase` ## フォーマット - 文字列にはダブルクォートを優先する - ステートメント末尾にセミコロンを付ける - `var` は絶対に使用しない — `const` を優先し、次に `let` - すべてのメソッド、パラメータ、戻り値には完全な型注釈を付ける ## ファイル構成 - コンポーネントファイル(`.ets`): ファイルごとに1つの `@ComponentV2` - ViewModel ファイル: ファイルごとに1つの ViewModel クラス - モデルファイル: 関連するデータモデルは同じファイルに共存可能 - ファイルは400行以内に収める。800行に近づく場合はヘルパーを抽出する ## コメント - ファイルヘッダー: `@file`(ファイルの目的)+ `@author`(開発者)— プロジェクトがすでにファイルヘッダーを使用している場合 - パブリックメソッド: JSDoc に `@param`、`@returns` を付ける。複雑なメソッドには `@example` を追加する - プロジェクトの既存のドキュメント言語に合わせる。リポジトリが中国語コメントを標準化していない限り英語を使用する ## エラーハンドリング ```typescript // 適切なエラーハンドリングで try/catch を使用する try { const result = await riskyOperation() return result } catch (error) { hilog.error(0x0000, 'TAG', 'Operation failed: %{public}s', error) throw new Error('User-friendly error message') } ``` ## イミュータビリティ 共通のイミュータビリティ原則に従う — ミューテートするのではなく新しいオブジェクトを作成する: ```typescript // BAD: ミューテーション function updateUser(user: UserModel, name: string): UserModel { user.name = name // 直接変更 return user } // GOOD: イミュータブル — 新しいインスタンスを作成 function updateUser(user: UserModel, name: string): UserModel { const updated = new UserModel() updated.id = user.id updated.name = name updated.email = user.email return updated } ```