nullを許容するプロパティを削除する

公開日: 

はじめに

TypeScript でオブジェクトの null を許容するプロパティを削除するための型を紹介します。

type Hoge = {
  name: string;
  age: number | null;
  address: string | null;
};

具体的には上のような型から

type Fuga = {
  name: string;
};

このような型を生成します。

結論

type ExcludeNullableProps<T> = Omit<
  T,
  {
    [K in keyof T]: null extends T[K] ? K : never;
  }[keyof T]
>;

こいつを利用することでオブジェクトの null を許容する型を削除できます。

利用方法

type ExcludeNullableProps<T> = Omit<
  T,
  {
    [K in keyof T]: null extends T[K] ? K : never;
  }[keyof T]
>;

type Hoge = {
  name: string;
  age: number | null;
  address: string | null;
};

type Fuga = ExcludeNullableProps<Hoge>;
// {
//   name: string
// }

解説

TypeScript のユーティリティタイプであるOmitを使用して、特定のプロパティを型から削除していきます。

https://typescriptbook.jp/reference/type-reuse/utility-types/omit

Omitとは第一型引数にオブジェクトの型、第二型引数にプロパティのキーを指定することで指定したキーを第一引数の型から削除した型を返します。それを利用するのですが、今回指定するキーは

{[K in keyof T]: null extends T[K] ? K : never}[keyof T]

上の結果生成される文字列リテラルのユニオン型です。

順を追って見ていきます。まず、

keyof T // ex. 'name'|'age'|'address'

keyof演算子を用いることで第一型引数のオブジェクト型のキーの文字列リテラルのユニオン型を生成します。

そしてin演算子を用いることで生成されるオブジェクト型のキーに先ほどのユニオン型の文字列を指定しています。簡単にするために型を string にしてみると以下のようになります。

// 簡単な例
{[K in keyof T]: string}
// ex.
// {
//   name: string
//   age: string
//   address: string
// }

次にプロパティの型を決めます。

null extends T[K] ? K : never

null が第一型引数のオブジェクト型のプロパティに入ることができるなら、キーの値を、できないなら never を型に指定します。

この処理を通した結果以下のような型が生成されます。

type Hoge = {
  name: never;
  age: 'age';
  address: 'address';
};

そして最終的にこいつの型から第一引数のキーのユニオン型を指定することで取得したい文字列のユニオン型を取得することができます。

先ほどの例で具体例を挙げると、

type Piyo = {
  name: never;
  age: 'age';
  address: 'address';
}[keyof Hoge];
// never|'age'|'address'

最終的に得られたユニオン型をOmitの第二型引数に指定してあげることで、null を許容する型を削除することができます。

もう一度最終的な型を載せておきます。

export type ExcludeNullableProps<T> = Omit<
  T,
  {
    [K in keyof T]: null extends T[K] ? K : never;
  }[keyof T]
>;

最後に

型パズルむずかちい

では

Bye