🎸

型のオプショナル化(Partial<Type>)と、ネストした型のオプショナル化 DeepPartial を作る

2024/10/28に公開1

APIにPostするタイミングで型は必須にしたいが、クライアントではオプショナルにしたかったのです

型のオプショナル化(Partial<Type>)

参考:
https://zenn.dev/atusi/articles/ee8ef5b3cc008f#7.-型のオプショナル化(partial<type>)

上記の記事より引用
// 例
interface User {
  name: string;
  age: number;
  address?: string;
}

// Userインターフェースのすべてのプロパティをオプションにする
type PartialUser = Partial<User>;

const user: PartialUser = {
  name: 'Taro', // ageは必須要素だったが、無くても定義可能となっている
};

ネストした型のオプショナル化: DeepPartial 作る

通常のPartialやと以下のような構造の型ですべてオプショナルにできない。nameの中身は必須のままになっちゃう。

interface User {
  name: {
    first: string;
    last: string;
  };
  age: number;
  address?: string;
}

どうするか参考

https://dev.to/perennialautodidact/adventures-in-typescript-deeppartial-2f2a

上記の記事より。結論
type DeepPartial<T> = T extends object ? {
        [P in keyof T]? : DeepPartial<T[P]> 
    } : T;

基本はこれでよさそう。ただこれやとArray型(例: string[])を含んだときに、(string | undefind)[]とかに変換されてうれしくない

おれの結論

type DeepPartial<T> =
  T extends Array<infer U>
    ? Array<U>
    : T extends object
      ? {
          [P in keyof T]?: DeepPartial<T[P]>;
        }
      : T;

Array型ではぱーしゃるぱーしゃるにしないことにした

よかったね

https://x.com/ksyunnnn/status/1850757894746358123