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] 特定の文字列を含む key をオプショナルにする

Last updated at Posted at 2023-07-17

やりたいこと

このような Object から

const user = {
    name: 'shiraishi',
    age_o: 30
}

このような型を作りたい。

type User = {
    name: string
    age?: number
}

解決方法

*_o というパターンのキー名から _o を取り除き、オプショナルに変更する型ユーティリティ関数 TransformedType を定義します

type TransformedType<T> = {
  [K in keyof T as K extends `${infer O}_o` ? O : never]?: T[K]
} & {
  [K in keyof T as K extends `${string}_o` ? never : K]: T[K]   
};

この関数を適用した結果が以下です。

type User = TransformedType<typeof user>

const test1: User = {
    name: 'name',
    age: 12
}

const test2: User = {
    name: 'name',
    age: 'age' // Type 'string' is not assignable to type 'number'.(2322)
}

const test3: User = {
    name: 'name',
}

const test4: User = {
    name: 'name',
    age: undefined
}

NG パターン

最初はより短く下記のように書いていました。

type TransformedType<T> = {
  [K in keyof T as K extends `${infer O}_o` ? O : K]: K extends `${string}_o` ? T[K] | undefined : T[K]
};

この書き方だと、age が無い場合にエラーになってしまいます。

// エラー
const test3: User = {
    name: 'name',
}

// OK
const test4: User = {
    name: 'name',
    age: undefined
}

背景

API 側のアプリケーションから自動生成されるレスポンスのサンプルの json からフロントエンドの型を自動生成しようとしたのが始まりです。
この json では optional かどうかが分からなかったため、キー名に optional かどうかが分かる情報を含めることにし、型ユーティリティ関数で型を作る方法を考えました。

参考

関連

この問題を解決する方法として、複数のレスポンスを含めた json 配列から型を生成する方法も考えました。

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?