TypeScriptである型の特定のプロパティの型を得る方法

type I = {
  func: (arg: string) => void;
};

という型があった時、Iの func プロパティの型を得るには、

const f: I["func"] = (arg) => {
  console.log(arg);
};

のように I["func"] とすると取得できます。

これはGenericsを使った型でも利用可能です。

type I<T> = {
  func: (arg: T) => void;
};

const f: I<string>["func"] = (arg) => {
  // arg は string
  console.log(arg);
};

デフォルト型引数が存在する場合は変数側での型引数の指定は必須ではなく、型推論も効きます。

type I<T = Record<string, unknown>> = {
  func: (arg: T) => void;
};

const f1: I["func"] = (arg) => {
  // arg は Record<string, unknown> として扱われるので `[]` で要素にアクセスできる
  console.log(arg["foo"]);
};

ライブラリにこういった複雑な型を渡す必要があるが、ライブラリ側からプロパティの型がexportされていない場合などに便利です。

TypeScriptでは Partial<T>Pick<T, K> などである型を変換した型 (Mapped Types) を作成できるので、特定のプロパティを抜き出すのもこういったUtility Typesでやるのかと思い込んでいたのですが、そうではなく T["property"] と書く、ということになかなか気付けませんでした。