keyofとvalueofを使いこなして、TypeScriptの型システムをさらに理解しよう

2024-04-02

TypeScriptにおけるkeyofとvalueof

回答: はい、valueofは存在しません。しかし、いくつかの方法で似たような機能を実現できます。

keyofはオブジェクト型からそのプロパティ名の集合(union型)を取得します。

interface Person {
  name: string;
  age: number;
}

type PersonKeys = keyof Person; // "name" | "age"

const key: PersonKeys = "name"; // "name"または"age"のみ代入可能
interface Person {
  name: string;
  age: number;
}

type PersonValues = valueof<Person>; // string | number

const value: PersonValues = "John Doe"; // "John Doe"または100など代入可能

valueofの代替方法

  1. 手動で列挙:
type PersonValues = string | number;
  1. keyoftypeofの組み合わせ:**
type PersonValues = typeof Person[keyof Person];
  1. ユーティリティ型:**
type ValueOf<T> = T[keyof T];

type PersonValues = ValueOf<Person>;

valueofは公式な型演算子ではありませんが、いくつかの方法で代替可能です。状況に合わせて最適な方法を選択してください。

補足

  • keyofはオブジェクト型だけでなく、配列型やジェネリック型にも使用できます。
  • typeofは変数や型の実際の値を取得するために使用できます。



// インターフェース定義
interface Person {
  name: string;
  age: number;
  isAdult: boolean;
}

// `keyof`の使用
type PersonKeys = keyof Person; // "name" | "age" | "isAdult"

// `valueof`の代替方法

// 1. 手動で列挙
type PersonValues1 = string | number | boolean;

// 2. `keyof`と`typeof`の組み合わせ
type PersonValues2 = typeof Person[keyof Person];

// 3. ユーティリティ型
type ValueOf<T> = T[keyof T];
type PersonValues3 = ValueOf<Person>;

// 各方法の動作確認
const key1: PersonKeys = "name"; // "name"または"age"または"isAdult"のみ代入可能
const value1: PersonValues1 = "John Doe"; // "John Doe"または100またはtrueなど代入可能
const value2: PersonValues2 = "John Doe"; // "John Doe"または100またはtrueなど代入可能
const value3: PersonValues3 = "John Doe"; // "John Doe"または100またはtrueなど代入可能

// オブジェクトの値へのアクセス
const person: Person = {
  name: "John Doe",
  age: 30,
  isAdult: true,
};

const name: string = person.name; // "John Doe"
const age: number = person.age; // 30
const isAdult: boolean = person.isAdult; // true

実行結果

// 特になし

注意事項

  • このコードはTypeScriptのバージョン4.1で動作確認しています。
  • ユーティリティ型ValueOfは、自分で定義する必要があります。
  • keyofvalueofは、オブジェクトリテラルやジェネリック型にも使用できます。
  • 詳細については、TypeScriptの公式ドキュメントを参照してください。



valueofを実現する他の方法

interface Person {
  name: string;
  age: number;
  isAdult: boolean;
}

const person: Person = {
  name: "John Doe",
  age: 30,
  isAdult: true,
};

const values: PersonValues = Object.values(person); // ["John Doe", 30, true]

type PersonValues = typeof values[number]; // string | number | boolean
interface Person {
  name: string;
  age: number;
  isAdult: boolean;
}

const person: Person = {
  name: "John Doe",
  age: 30,
  isAdult: true,
};

const values: PersonValues = Object.keys(person).map(key => person[key]); // ["John Doe", 30, true]

type PersonValues = typeof values[number]; // string | number | boolean

ユーティリティライブラリの使用

lodashなどのユーティリティライブラリには、valueofに似た機能を提供する関数があります。

import { valueof } from "lodash";

interface Person {
  name: string;
  age: number;
  isAdult: boolean;
}

const person: Person = {
  name: "John Doe",
  age: 30,
  isAdult: true,
};

const values: PersonValues = valueof(person); // ["John Doe", 30, true]

type PersonValues = typeof values[number]; // string | number | boolean
  • 简单的なケースでは、Object.valuesを使うのが最も簡単です。
  • より複雑なケースでは、keyofmapの組み合わせを使う方が柔軟性があります。
  • ユーティリティライブラリを使うと、コードを簡潔に書けますが、ライブラリの依存関係が増えてしまいます。

typescript types


インターフェースマスターへの道! TypeScript インターフェースの深い理解

インターフェースを他のモジュールで使用できるようにするには、エクスポートする必要があります。インターフェースの前にexportキーワードを追加することで、インターフェースをデフォルトでエクスポートできます。他のモジュールで定義されたインターフェースを使用するには、importキーワードを使ってインポートする必要があります。...


より安全で保守性の高い TypeScript コードを書く

しかし、プログラムを実行中に、ある値が特定のユニオン型に属するかどうかを確認したい場合があります。このような場合、型ガードと呼ばれる機能を使用することができます。型ガードは、式の結果に基づいて変数の型を絞り込むための仕組みです。具体的には、typeof 演算子、instanceof 演算子、in 演算子、=== 演算子などの条件式を使用して、変数の型が特定の型であるかどうかを判定することができます。...


TypeScript インターフェース: どちらか一方の属性を必須にする2つの方法

この場合、以下の2つの方法で実現できます。never 型は、決して存在しない値を表す型です。この型を利用して、以下の方法で「どちらか一方」の属性を必須にできます。このコードでは、firstProperty と secondProperty という2つの属性を定義しています。...


React、TypeScript、Webpack で "Invalid configuration object" エラーを回避する: 原因と解決策

解決策このエラーを解決するには、以下のいずれかの方法を試すことができます。Webpack のバージョンを更新する古いバージョンの Webpack を使用している場合は、最新バージョンに更新してみてください。多くの場合、Webpack の最新バージョンには、古い構文との互換性を向上させるための変更が含まれています。...


Angularで発生する「ActivatedRoute dataが空のオブジェクト」問題:原因と解決策をわかりやすく解説

レイジーロードモジュールの対策: レイジーロードモジュールの場合は、以下のいずれかの方法で対策できます。dataプロパティをモジュール内のルート設定に直接定義する。グローバルなリゾルバを使用する。forChildプロパティを使用して子ルート設定にdataプロパティを定義する。...