SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

JavaScriptの限界を超える!TypeScript初めの一歩

【TypeScriptの基礎を学ぶ】TypeScriptの型の付け方・あつかい方を解説

JavaScriptの限界を超える!TypeScript初めの一歩 第2回

  • X ポスト
  • このエントリーをはてなブックマークに追加

typeof型演算子とkeyof型演算子

 ここからは、少しマニアックな内容です。型についての情報をあつかうTypeScriptの型演算子を2つ示します。typeof型演算子と、keyof型演算子です。

 「typeof」「型演算子」、「keyof」「型演算子」です。単語の区切り位置に注意してください。また、typeof型演算子は、JavaScriptのtypeof演算子とは別物なので、混同しないようにしてください。

 typeof型演算子は、変数から型を抽出します。例を示します。

let user = { name: "Tom", age: 10 };
type User = typeof user;
let user2: User = { name: "Bob", age: 11 };

 userから型を得て、Userに型を代入して、user2: Userと利用しています。

 このtype User = typeof user;の部分はTypeScript独自の処理なので、npx tscでコンパイルすると消えます。npx tsc main.ts --target es2024でコンパイルしたファイルは、次のようになります。あくまでも型をあつかう演算子なのが分かると思います。

let user = { name: "Tom", age: 10 };
let user2 = { name: "Bob", age: 11 };

 続いて紹介するkeyof型演算子は、オブジェクトの型から、プロパティ名を型として返します。例を示します。

type Chara = {
    name: string;
    hp: number;
    mp: number;
 };
type CharaKey = keyof Chara;

 型エイリアスCharaKeyには、"name" | "hp" | "mp"が入ります。下の2つは同じ意味を持ちます。

type CharaKey = keyof Chara;
type CharaKey = "name" | "hp" | "mp";

 keyof型演算子は、プロパティ名の一覧の型を得ますので、プロパティ名のチェックに有用です。例を示します。

function getProfile(chara: Chara, prop: CharaKey): string {
    return `${chara.name}: ${chara[prop]}`;
}
let chara: Chara = { name: "Tom", hp: 10, mp: 5 };
console.log(getProfile(chara, "hp"));
console.log(getProfile(chara, "mp"));
console.log(getProfile(chara, "ap"));   // エラーになる

 CharaKeyを使って関数の引数をチェックします。最後の行の"ap"は、関数の引数prop: CharaKeyには使えないのでエラーが出ます。

 VSCodeで、この部分の赤線にマウスカーソルを重ねるとArgument of type '"ap"' is not assignable to parameter of type 'keyof Chara'.("ap"' 型の引数は 'keyof Chara' 型のパラメータに割り当てることができません。)と表示されます。

 自動でプロパティのユニオン型を作ってくれるのでメンテナンスが楽になります。

インターフェース

 TypeScriptでは、クラスのインターフェースを実装できます。このインターフェースはTypeScriptの機能なので、コンパイルしてJavaScriptに出力すると消されるので注意が必要です。

 TypeScriptのインターフェースの例を示します。JavaScriptのクラスのようにinterfaceを書きます。クラスへの適用はimplementsを使います。また、複数適用して実装するには、,で区切ります。

interface Chara {
    name: string;
    walk(): void;
}

interface StatMagick {
    cast(): void;
}

class Mage implements Chara, StatMagick {
    name: string = "魔術師";
    walk(): void {
        console.log(`${this.name}、てくてく`);
    };
    cast(): void {
        console.log(`${this.name}、どっかーん`);
    };
}

let mage = new Mage();
mage.walk();
mage.cast();

 implements Chara, StatMagickの部分が、インターフェースを利用している部分になります。

 また、インターフェースのフィールドにもreadonlyを付けられます。

interface User {
    readonly id: number;
    name: string;
    userType: string;
}

 インターフェースはextendsで継承できます。その際に、継承元のフィールドを宣言し直すこともできます。

interface Publisher extends User {
    userType: "Publisher";
    item: string[];
}

 また、TypeScriptのインターフェースには、少し変わった特徴があります。同じ名前のインターフェースを宣言するとマージされます。

 下に示す1つ目のコードと、2つ目のコードは同じ意味になります。

interface CatAct {
    walk(): void;
}

interface CatAct {
    meow(): void;
}
interface CatAct {
    walk(): void;
    meow(): void;
}

TypeScriptと構造的型付け

 プログラミング言語の世界では、型が同じか違うかを判別する方法は1つだけではありません。たとえばJavaでは、クラス名と継承構造を使って、同じか違うかを判断します。そしてTypeScriptでは、構造を見て、同じか違うかを判断します。

 例を示します。

class Elf {
    talk(): void {};
};

class Human {
    talk(): void {}
};

let elf: Elf = new Elf();
let human: Human = elf;

 上のコードでは、クラスElfのインスタンスを作り、型注釈としてHumanを指定した変数humanに代入します。これはエラーが起きません。

 Humantalk()を持つ存在で、Elftalk()を持っているのでHumanと見なせるからです。

 こうしたプロパティは、完全に一致している必要はありません。条件を満たしていれば、不要なプロパティを持っていても構いません。例を示します。

class Elf {
    talk(): void {};
    castMagick(): void {}
};

class Human {
    talk(): void {}
};

let elf: Elf = new Elf();
let human: Human = elf;

 ElfにはcastMagick()というHumanにはないプロパティがあります。しかし、Humanの条件であるtalk()を持っているのでHumanと見なせます。

3. まとめと次回予告

 今回は、TypeScriptで型をあつかってきました。次回からは、さらに多様なデータに対応していきます。

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
JavaScriptの限界を超える!TypeScript初めの一歩連載記事一覧
この記事の著者

柳井 政和(ヤナイ マサカズ)

クロノス・クラウン合同会社 代表社員http://crocro.com/オンラインソフトを多数公開。プログラムを書いたり、ゲームを作ったり、記事を執筆したり、マンガを描いたり、小説を書いたりしています。「めもりーくりーなー」でオンラインソフト大賞に入賞。最近は、小説家デビューして小説も書いています(『裏切りのプログラム』他)。面白いことなら何でもOKのさすらいの企画屋です。 

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/21596 2025/08/01 11:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング