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?

More than 1 year has passed since last update.

【Typescript】型推論されたオブジェクト型のキーをオプショナルにした型を作る

Last updated at Posted at 2022-04-16

絶対に忘れるのでメモ。

2022-04-18追記
知識浅すぎて悲しくなりました。
Partialというそれ用の型宣言方法がありました。

内部でやってることはこの記事と似てる。

やりたいこと

変数宣言時にオブジェクト型を代入すると勝手にその値のkeyを持った型として定義される。
そのオブジェクト型変数のキーをオプショナルにした上で他の変数の型として使いたい。

単純にその型を書けばいいんだけど面倒なので書きたくない。
新しく追加するたびに型の部分も値の部分も直さなきゃだし。

const ErrorMessages: {
  // ここを書きたくない
  logInFaild?: string;
  invalidValue?: string;
} = {
  logInFaild: 'ユーザー名かパスワードが間違っています。',
  invalidValue: '数値で入力してください。',
}

const messages: typeof ErrorMessages = {}

結論

ここまでの内容で察せられる人用。

const ErrorMessages = {
  logInFaild: 'ユーザー名かパスワードが間違っています。',
  invalidValue: '数値で入力してください。',
}
type keys = keyof typeof ErrorMessages
type ErrorMessageType = {[key in keys]?: string }

const messages: ErrorMessageType = {}
// ↓定義される型
type ErrorMessageType = {
  logInFaild?: string | undefined
  invalidValue?: string | undefined
}

詳しく

オブジェクト型(辞書型)を変数に入れると型推論によって勝手に型が決まる。

例としてはこんなシチュエーション。

表示するメッセージの一覧的な定数(=メッセージ辞書)を作る。
実際にメッセージを入れておく変数には、メッセージ辞書のキーと値を入れる。

メッセージ変数のキーはメッセージ辞書に存在するもののみに制限したい。
そのメッセージが不要な時は値を入れたくないのでオプショナルにもしたい。

コードにするとこう↓

const ErrorMessages = {
  logInFailed: 'ユーザー名かパスワードが間違っています。',
  invalidValue: '数値で入力してください。',
}

const messages = {}

if (login()) {
  // ログイン成功
} else {
  // ログイン失敗
  messages.logInFailed = ErrorMessages.logInFailed // エラー
}

このままだとmessagesには{}型、つまり「キーを持たないオブジェクト型」が定義されているのでエラー部分でエラーになる。

Property 'logInFailed' does not exist on type '{}'

解決方法(結論部分の説明)

typeofkeyofinMapped Typesを組み合わせて解決する。

まずtypeofkeyofで「メッセージ辞書のキーのみを入れられるstring型」を作る。

const ErrorMessages = {
  logInFaild: 'ユーザー名かパスワードが間違っています。',
  invalidValue: '数値で入力してください。',
}

type keys = keyof typeof ErrorMessages
// 実際に作成される型
// type keys = "logInFaild" | "invalidValue"

Mapped Typesでキーを制限したオブジェクト型を作るが、その時に?を付けてオプショナルにする。

type ErrorMessageType = {
  [key in keys]?: string // `key`には'logInFaild'と'invalidValue'しか入れられない
}

これでメッセージ変数を宣言すればキーがオプショナルなオブジェクト型ができる。

const messages: ErrorMessageType = {}
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?