1. 3 件中 2 件が公開中
  2. 公開作品が 1 件だけ
  3. 下書きしか無い
  4. 作品がまだ 1 件も無い
  5. 3 件すべて公開中
コース一覧
TypeScript型設計:オブジェクト・状態・ジェネリクス
つくる - Work型とProfile型

TypeScript型設計:オブジェクト・状態・ジェネリクス

interface、optional property、readonly、union・リテラル型、型ガード、ジェネリクスを扱う全23レッスンの型設計コースです。Profile・Work・ApplicationStateを題材に、APIや画面で扱うデータと状態を壊れにくい型として設計します。既存JavaScriptプロジェクトの移行は次のコースで扱います。

1
オブジェクト型とinterface
01. interface15分
02. 省略可能なプロパティ15分
03. readonly15分
04. interfaceとtype15分
05. ネストした型15分
06. オブジェクト配列15分
07. つくる - Work型とProfile型20分
08. 第4章クイズ15分
2
union・リテラル型・型ガード
01. union型15分
02. リテラル型15分
03. 状態のunion15分
04. typeofで絞り込む15分
05. inと判別で絞り込む15分
06. 状態で表示を切り替える15分
07. つくる - 状態の型表現20分
08. 第5章クイズ15分
3
ジェネリクス入門
01. なぜジェネリクスか10分
02. ジェネリック関数15分
03. 配列を返す汎用関数15分
04. 制約付きジェネリクス15分
05. 組み込みのジェネリクス15分
06. つくる - 汎用フィルタ関数20分
07. 第6章クイズ15分

つくる - Work型とProfile型

第4章で育てた形を確定させる

この回で新しい知識は出てきません。第4章で 1 つずつ足してきたものを、そのまま 1 か所にまとめます。

使ったのは次の 5 つです。interface、省略可能なプロパティ、readonly、interface と type の使い分け、ネストした型とオブジェクト配列です。

確定する Work 型

TypeScript

interface Author { name: string; nickname: string; } interface Work { readonly id: number; title: string; published: boolean; url?: string; author: Author; }

id は作品を見分ける番号なので readonly、url は下書きには無いので省略可能、author は入れ子です。ここまでで決めた形と 1 文字も変わっていません。

追加する Profile 型

作者本人のプロフィールは、作品一覧を持ちます。

TypeScript

interface Profile { readonly id: number; name: string; bio: string; works: Work[]; }

works が Work[] なので、Profile を 1 つ渡せば、その人の作品もまとめて型が付いた状態で運べます。

これは持ち出す資産です

Work と Profile は、このコースの残りだけでなく、React 実践のコースでもそのまま使います。props の型も、fetch した結果の型も、この 2 つを起点に書いていきます。

だからプロパティ名を思いつきで変えないでください。title を name にしたり、published を isPublic にしたりすると、後のコースの説明と噛み合わなくなります。

手を動かす

演習では、上の 3 つの型を自分で書き、Profile を受け取って一行の要約を返す関数を作ります。要約には名前、公開作品の件数、公開作品のタイトルを並べます。ここまでのレッスンで書いたコードを見返しながら組み立ててください。

要件

  1. Author Work Profile の 3 つの型を定義する
  2. Work の id は readonly、url は省略可能にする
  3. 名前さん / 公開作品N件 / タイトル、タイトル の形で返す。タイトルの区切りは全角読点
  4. 公開作品が 0 件のときは末尾を まだ公開作品はありません にする

入出力例

profileSummary({"bio":"Web制作を学習中です","id":1,"name":"ゆめさく","works":[{"author":{"name":"ゆめさく","nickname":"yume"},"id":1,"published":true,"title":"プロフィールサイト","url":"https://example.com/portfolio"},{"author":{"name":"ゆめさく","nickname":"yume"},"id":2,"published":false,"title":"自己紹介カード"},{"author":{"name":"ゆめさく","nickname":"yume"},"id":3,"published":true,"title":"スキル一覧の表"}]}) → "ゆめさくさん / 公開作品2件 / プロフィールサイト、スキル一覧の表" profileSummary({"bio":"はじめました","id":2,"name":"たなか","works":[{"author":{"name":"たなか","nickname":"tanaka"},"id":1,"published":true,"title":"プロフィールサイト"}]}) → "たなかさん / 公開作品1件 / プロフィールサイト" profileSummary({"bio":"準備中です","id":3,"name":"さとう","works":[{"author":{"name":"さとう","nickname":"sato"},"id":1,"published":false,"title":"自己紹介カード"}]}) → "さとうさん / 公開作品0件 / まだ公開作品はありません" profileSummary({"bio":"これから作ります","id":4,"name":"すずき","works":[]}) → "すずきさん / 公開作品0件 / まだ公開作品はありません" profileSummary({"bio":"Web制作を学習中です","id":5,"name":"ゆめさく","works":[{"author":{"name":"ゆめさく","nickname":"yume"},"id":1,"published":true,"title":"プロフィールサイト"},{"author":{"name":"ゆめさく","nickname":"yume"},"id":2,"published":true,"title":"自己紹介カード"},{"author":{"name":"ゆめさく","nickname":"yume"},"id":3,"published":true,"title":"スキル一覧の表"}]}) → "ゆめさくさん / 公開作品3件 / プロフィールサイト、自己紹介カード、スキル一覧の表"

ヒント

先に `Author` を書き、次に `Work`、最後に `Profile` の順で定義すると詰まりません

公開中だけ残すのは `filter`、タイトルだけ取り出すのは `map` です

タイトルをつなぐのは `join("、")` です。0 件のときは join を使わず別の文字列を返します

生田 陸人
監修生田 陸人
ゆめさくエンジニア / 現役ソフトウェアエンジニア監修者プロフィールを見る →
編集 ゆめさく編集部·公開 2026/08/06

関連レッスン

  • 第4章クイズ

    interfaceとオブジェクト型の理解を確認します。

  • union型

    文字列または数値を受ける値を書き、AまたはBを型にできるようになります。

  • なぜジェネリクスか

    any版の汎用関数で起きる事故を見て、型引数で汎用化する動機を説明できるようになります。

このレッスンに出てくる用語

意味があいまいなまま進んだ語は、ここから読み直せます。

  • interface実装を持たないメソッド契約。複数 implements 可
  • プロパティメソッドを属性のようにアクセスできるようにするデコレータ。
  • オブジェクトキーと値のペアで構造を作るデータ
  • 配列サイズ固定の同型データの集まり
  • fetchブラウザ標準の HTTP クライアント API
  • 関数処理に名前を付けて再利用できる単位
main.ts
学習モード
エディタを読み込んでいます

メモ

つくる - Work型とProfile型

⌘S で保存