0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【TypeScript】type-challenges 中級編 8・Readonly 2 解説

Posted at

お題

Kが指定されている場合、オブジェクト型Tの中のKのプロパティのみを読み取り専用にし、Kが指定されていない場合、通常のReadonly<T>と同様に、すべてのプロパティを読み取り専用にする型MyReadonly2を実装する。

やりたいこと

interface Todo {
  title: string
  description?: string
  completed: boolean
};

type Expected = MyReadonly2<Todo, 'title' | 'description'>;

interface Expected {
  readonly title: string
  readonly description?: string
  completed: boolean
};

解答

type MyReadonly2<T, K extends keyof T = keyof T> = {
  readonly [P in K]: T[P]
} & {
  [P in keyof T as P extends K ? never : P]: T[P]
};

解説

処理の流れ

  • <T, K extends keyof T = keyof T>
    • Kに入る値を、Tのプロパティのみに制約
    • default valueを使用し、Kが指定されない場合はkeyof Tが割り当てられる
      Kが指定されない場合に、すべてのプロパティが読み取り専用になる)
  • { readonly [P in K]: T[P] }
    Mapped Typesを使用し、Kのプロパティのみの読み取り専用オブジェクトを作成。
  • { [P in keyof T as P extends K ? never : P]: T[P] }
    Mapped Typesとasを使用し、元の型を保持したK以外のプロパティのオブジェクトを作成。
  • {...} & {...}
    インターセクション型(&)を使用し、オブジェクトを合成する。

default valueとは...

引数がundefinedのとき、代わりの値を指定できる
JavaScriptは引数を省略すると、undefinedが返される。

// 書き方
function 関数名(引数 = デフォルト値) {}

// 型注釈を入れる場合
function 関数名(引数:  = デフォルト値) {}

インターセクション型(&)とは...

合成したいオブジェクト同士&で列挙することで、インターセクション型を作る。

type A = { name: string };
type B = { age: number };

type AB = A & B; // { name: string; age: number; }

プリミティブ型のインターセクション型
neverが返される。

type Never = string & number; // never

keyof演算子とは...

Mapped Typesとは...

Mapped Typesにおける「as」とは...

参考記事

default value

インターセクション型

今回の問題

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?