53
43

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

TypeScriptに既にある機能と無駄に同じような実装をしてみた

Posted at

はじめに

※この記事を読まれるのは確実に時間の無駄です

それでも見てみよっかなという心優しいお方だけお付き合いください。

記事の内容について

TypeScriptがすでに準備してくれている便利な Utility Types ですが、無駄に同じような機能を作ってみようと思います。

完全に車輪の再開発で全く意味はありません

型パズルでただの趣味です。

Pick

「Pick」は既に存在するT型の中からKで選択した一部のプロパティのみを含んだ新たな型を構築します。

Utility Types

まずはTypeScriptの Utility Types でやってみます。

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

type PickedType = Pick<Person, 'name'>

結果は以下の通りです。

UtilityTypesの結果
type PickedType = {
  name: string;
}

はい、便利です。

オレオレPick

では自前で実装してみます。

オレオレPick
type OrenoPick<T, K extends keyof T> = {
  // [key in K] は Mapped Types
  // T[key] は Indexed Access Types で K からキャプチャされた key によってアクセス
  [key in K]: T[key]
}

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

type PickedType = OrenoPick<Person, 'name'>

結果は以下の通りです。

オレオレPickの結果
type PickedType = {
  name: string;
}

Parameters

続いては、Parametersです。
Parametersは関数型Tの引数の型をタプル型として抽出した型を構築します。

Utility Types

まずは、Utility Typesからです。

UtilityTypes
const foo = (arg: { a: number, b: string }): void => {}

type Hoge = Parameters<typeof foo>;
UtilityTypesの結果
type Hoge = [arg: {
    a: number;
    b: string;
}]

オレオレParameters

オレオレParameters
const foo = (arg: { a: number, b: string }): void => {}

// 「(...args: any[]) => any」を extends することで、Tが関数であるという制約を設ける
type OrenoParameters<T extends (...args: any[]) => any> 
  = T extends (...args: infer R) => 
  unknown ? R : never

type Hoge = OrenoParameters<typeof foo>;
オレオレParametersの結果
type Hoge = [arg: {
    a: number;
    b: string;
}]

はい、こちらも一致しました。

infer については以下の記事で少しだけ解説しておりますのでもし宜しければご参考下さい。

さぁ、次にいきましょう。

Readonly

ReadonlyはTの全てのプロパティをreadonlyのプロパティにしてくれます。

Utility Types

UtilityTypes
interface Todo {
  title: string;
}
 
const todo: Readonly<Todo> = {
  title: "Delete inactive users",
};
 
todo.title = "Hello"; // Cannot assign to 'title' because it is a read-only property.

オレオレReadonly

オレオレReadonly
type OrenoReadonly<T> = {
  // Mapped Types で readonly をつける
  readonly [key in keyof T]: T[key]
}

interface Todo {
  title: string;
}
 
const todo: OrenoReadonly<Todo> = {
  title: "Delete inactive users",
};
 
todo.title = "Hello"; // Cannot assign to 'title' because it is a read-only property.

はい、ちゃんと書き込み時にエラーになりました。

ここであることに気づく

UtilityTypes にマウスオーバーすると、めっちゃ親切に内部実装を見せてくれる。。。

1.png

定義にジャンプしなくても.d.tsがあるからそりゃそうだよね、
ということで、これ以上やる意味がないと判断し終了いたします。

まぁ、頭の体操にはよかったかな、、、と思うことにします。。

以上です。
最後まで読んで下さった心優しい方に感謝。

53
43
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
53
43

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?