0Pricing
TypeScript Academy · レッスン

文字列インデックスシグネチャと数値インデックスシグネチャ

数値キーに関するルールと特有の挙動を理解します。

「文字列インデックスシグネチャと数値インデックスシグネチャ」はCoddyKit上の無料TypeScript Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはTypeScript Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 TypeScript Academyコースには全4レッスンが含まれています。

インデックスキーの2つの種類

TypeScriptは文字列と数値の両方のインデックスシグネチャをサポートしています。見た目は似ていますが、JavaScriptが実際にオブジェクトのキーを保存する方法によって動作が異なります。

数値インデックスシグネチャ

数値インデックスシグネチャ { [i: number]: T } は、数値の位置でインデックス付けされるオブジェクトを表します。最も自然な例は、配列や配列に似た構造です。

type NumberList = { [index: number]: string }

const names: NumberList = { 0: "ana", 1: "leo" }
console.log(names[0]) // ana

JSは数値キーを文字列に変換する

ここで重要なのは、JavaScriptのオブジェクトキーは常に文字列だということです。obj[0] と記述すると、実際にはエンジンによってキーが文字列 "0" として保存されます。TypeScriptはこの実態をモデル化しています。

const obj: Record<string, string> = {}
obj[1] = "one"
console.log(obj["1"]) // one — same key!
console.log(Object.keys(obj)) // ["1"]

互換性のルール

数値キーは内部的には文字列なので、TypeScriptは次のルールを適用します。オブジェクトが数値と文字列の両方のインデックスシグネチャを持つ場合、数値インデックスの値の型は、文字列インデックスの値の型に代入可能でなければなりません。

interface Mixed {
  [key: string]: string
  [index: number]: string // must match the string value type
}
const m: Mixed = { 0: "a", name: "b" }
console.log(m[0], m.name)

このルールが存在する理由

obj[0] と obj["0"] が同じ場所を参照するなら、一方の値の型を数値、もう一方を文字列にすることはできません。整合性を保つため、数値インデックスの値の型は文字列インデックスの値の型のサブタイプでなければなりません。

// This is an ERROR:
// interface Bad {
//   [key: string]: string
//   [index: number]: number // number not assignable to string
// }

数値インデックス型:配列

配列は、数値でインデックス付けされる型の代表例です。組み込みの Array<T> 型は実質的に数値インデックスシグネチャを持つため、arr[i] は T を返します。

const nums: number[] = [10, 20, 30]
const first: number = nums[0]
console.log(first + nums[2]) // 40

タプルも数値でインデックス付けされる

タプルは数値インデックスを基盤としながら、特定の位置に特定の型を割り当てます。範囲外の数値アクセスは要素型のユニオンにフォールバックするか、エラーとして通知されます。

const pair: [string, number] = ["age", 30]
const label: string = pair[0]
const value: number = pair[1]
console.log(label + ": " + value)

文字列インデックスではどちらのアクセスも可能

文字列インデックスシグネチャを持つオブジェクトでは、数値に見えるキーによるアクセスも受け付けます。これは、数値がまず文字列キーに変換されるためです。

type Bag = { [key: string]: number }
const b: Bag = {}
b[5] = 100        // stored as key "5"
console.log(b["5"]) // 100

数値インデックスでは文字列を受け付けない

逆は成り立ちません。数値インデックスシグネチャだけで型付けされたオブジェクトは、JavaScriptでは技術的に許可される場合でも、コンパイル時には文字列キーを拒否します。

type OnlyNumbers = { [i: number]: string }
const o: OnlyNumbers = { 0: "x" }
// o.name = "y" // Error: property name not on number-indexed type
console.log(o[0])

どちらを選ぶか

シーケンスのような位置ベースのデータ(リストやタプル)には数値インデックスを使用します。名前で検索するデータ(辞書やキャッシュ)には文字列インデックスを使用します。迷った場合は、より汎用的な文字列を選ぶとよいでしょう。

type Positions = { [i: number]: { x: number; y: number } }
type ByName = { [name: string]: { x: number; y: number } }
const p: Positions = { 0: { x: 1, y: 2 } }
console.log(p[0].x)

実用的な混在オブジェクト

両方のシグネチャで同じ値の型を使用できる場合は、両方を組み合わせられます。名前付きのスロットも公開する、疎な配列のようなコンテナーに便利です。

interface Flexible {
  [key: string]: number
  [index: number]: number
}
const f: Flexible = { 0: 1, total: 99 }
console.log(f[0] + f.total) // 100

理解度チェック

文字列インデックスと数値インデックスの違いについての理解度を確認しましょう。

まとめ

JSはすべてのキーを文字列として保存し、数値を文字列キーに変換するため、文字列インデックスと数値インデックスの動作は異なります。両方が存在する場合、数値インデックスの値の型は文字列インデックスの値の型に代入可能でなければなりません。数値インデックスは配列やタプルをモデル化し、文字列インデックスは辞書をモデル化します。文字列インデックスを持つオブジェクトでは数値でアクセスできますが、数値インデックスを持つオブジェクトではコンパイル時に文字列キーが拒否されます。

よくある質問

「文字列インデックスシグネチャと数値インデックスシグネチャ」レッスンは無料ですか?

はい。「文字列インデックスシグネチャと数値インデックスシグネチャ」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、TypeScript Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 TypeScript Academyコースには全4レッスンが含まれています。

「文字列インデックスシグネチャと数値インデックスシグネチャ」で何を学びますか?

数値キーに関するルールと特有の挙動を理解します。 ブラウザで直接実行するハンズオンコードでTypeScript Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

TypeScript Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのTypeScript Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。

「文字列インデックスシグネチャと数値インデックスシグネチャ」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このTypeScript Academyレッスンでコードを書いて実行できますか?

はい。すべてのTypeScript Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. インデックスシグネチャの定義
  2. 文字列インデックスシグネチャと数値インデックスシグネチャ
  3. 既知のキーと動的なキーの組み合わせ
  4. インデックスシグネチャとRecord
← TypeScript Academyに戻る