問題
組み込みの型ユーティリティ`Readonly<T>`を使用せず、`T` のすべてのプロパティを読み取り専用にする型を実装します。実装された型のプロパティは再割り当てできません。
例えば:
```ts
interface Todo {
title: string
description: string
}
const todo: MyReadonly<Todo> = {
title: "Hey",
description: "foobar"
}
todo.title = "Hello" // Error: cannot reassign a readonly property
todo.description = "barFoo" // Error: cannot reassign a readonly property
```
TypeScriptの組み込みユーティリティ型Readonly
を使用せずにすべてのプロパティを読み取り専用にする型を作成してくださいという問題です。
JSのreadonly修飾子を禁じられているわけではないのでご注意ください。(一敗)
回答
type MyReadonly<T> = {
readonly [key in keyof T] : T[key]
}
初級だけありかなり単純ですね。
詳細解説
keyof T
T
のすべてのプロパティ名のユニオン型を生成します。
例えば T が { a: number, b: string }
なら、keyof T
は "a" | "b" になります
Mapped Types(マッピング型)
[key in keyof T]
の部分は、T の各プロパティ名を取り出し、対応するプロパティを生成するための構文です。
readonly 修飾子
readonly
を付けることで、オブジェクト生成後にそのプロパティが変更できなくなります。
T[key]
元の型 T の各プロパティの型がそのまま引き継がれます
例えば以下のような場合
{
a: "aaa",
b: "bbb",
c: "ccc",
}
keyof T
でプロパティ名のユニオン型を生成すると "a" | "b" | "c" となり、[key in keyof T]
で "a" | "b" | "c" がプロパティ名のオブジェクトが作成されます。
そして各プロパティのvalueはT[key]
なので...
{
a: `T["a"]` // -> "aaa"
b: `T["b"]` // -> "bbb"
c: `T["c"]` // -> "ccc"
}
と、元のオブジェクトが復元されるような形となります。