5
4

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 3 years have passed since last update.

【TypeScript】Objectのkeyによってvalueの型を推論するテクニック

Last updated at Posted at 2020-11-26

:question: Problem

次の関数changeValueByKeyようにObjectのkeyによってvalueを変更する関数を型安全に作りたい!

type State = {
  text: string;
  isActive: boolean;
};

let state: State = {
  text: "",
  isActive: false
}

const changeText = (value: string) => {
  // OK
  state['text'] = value;
}

const changeIsActive = (value: boolean) => {
  // OK
  state['isActive'] = value;
}

const changeValueByKey = (key: 'text' | 'isActive', value: string | boolean) => {
  // Type Error
  state[key] = value;
}

:star2: Solution

type State = {
  text: string;
  isActive: boolean;
};

let state: State = {
  text: "",
  isActive: false
}

const changeValueByKey = <K extends keyof State>(key: K, value: State[K]) => {
  state[key] = value;
}

// OK
changeValueByKey('text', 'test')
changeValueByKey('isActive', true)

// Type Error
changeValueByKey('text', true)
changeValueByKey('isActive', 'test')
  • 解説
    • keyofを使うことでプロパティ名のtypeを参照することができます
    • keyof StateでStateのプロパティ名を参照し、それをextends継承したtypeKをGenericsとして用意します
    • 第一引数keyはプロパティ名なのでそのままKを使用し、第二引数valueはStateのプロパティKのvalueの型なのでState[K]とします
    • これでkeyはtext | isActiveとなり、keyを指定した時にvalueの型が決まるようになります
    • keyにtextを指定した時にvalueはState['text']なのでstringに、isActiveを指定した時にvalueはState['isActive']なのでbooleanしか渡せないようになりました
  • 今すぐ動作を確認してみたい方はこちら

TypeScriptに対応したEditorならサジェストも出ます
スクリーンショット 2020-11-26 21.57.32.png

:pencil: Demo

See the Pen Demo: change object value type by key by mikan3rd (@mikan3rd) on CodePen.

↑ Code SandboxはQiitaに埋め込みできないようなのでCodePenを埋め込んであります
(ただしCodePenではType Errorなどは出ません・・・)

5
4
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
5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?