@@ -5,10 +5,62 @@ export type JSON$stringifyT = <T>(
55 data : T ,
66 replacer ?: undefined ,
77 space ?: number | string | undefined ,
8- ) => TypedString < T > ;
8+ ) => TypedString < JsonStringifyResult < T > > ;
99
1010type JSONT = Omit < JSON , "stringify" > & {
1111 stringify : JSON$stringifyT ;
1212} ;
1313
1414export default JSONT ;
15+
16+ // JSONとして有効なプリミティブ型 + Date
17+ type JsonPrimitive = string | number | boolean | null | Date ;
18+
19+ // undefined | function | symbol | bigint は JSON化できない (除外 or null or エラー)
20+ // eslint-disable-next-line @typescript-eslint/ban-types
21+ type InvalidJsonValue = undefined | Function | symbol | bigint ;
22+
23+ // 配列要素の変換: 不適切な値は null に
24+ type JsonifyArrayElement < T > = T extends InvalidJsonValue ? null : Jsonify < T > ;
25+
26+ // オブジェクトの変換
27+ type JsonifyObject < T > = {
28+ // keyof T から string 型のキーのみを抽出 (シンボルキーを除外)
29+ [ K in keyof T as K extends string
30+ ? // プロパティの値 T[K] を Jsonify した結果を ProcessedValue とする
31+ Jsonify < T [ K ] > extends infer ProcessedValue
32+ ? // ProcessedValue が 不適切な型なら、このプロパティ自体を除外 (never)
33+ ProcessedValue extends InvalidJsonValue
34+ ? never
35+ : // そうでなければキー K を採用
36+ K
37+ : never
38+ : never ] : Jsonify < T [ K ] > ; // ↑で採用されたキー K に対して、変換後の値 ProcessedValue を割り当て
39+ } ;
40+
41+ // メインの再帰型
42+ type Jsonify < T > =
43+ // 1. toJSONメソッドを持つか? -> あればその返り値を Jsonify
44+ T extends { toJSON ( ) : infer R }
45+ ? Jsonify < R >
46+ : // 2. Dateか? -> string
47+ T extends Date
48+ ? string
49+ : // 3. その他のプリミティブか? -> そのまま
50+ T extends JsonPrimitive
51+ ? T
52+ : // 4. 不適切な値か? -> そのまま (呼び出し元で処理)
53+ T extends InvalidJsonValue
54+ ? T
55+ : // 5. 配列か? -> 各要素を JsonifyArrayElement で変換
56+ T extends Array < infer E >
57+ ? Array < JsonifyArrayElement < E > >
58+ : // 6. オブジェクトか? -> JsonifyObject で変換
59+ T extends object
60+ ? JsonifyObject < T >
61+ : // 7. それ以外 (通常は到達しない) -> never
62+ never ;
63+
64+ // 最終的な型: トップレベルでの undefined/function/symbol/bigint は undefined になる
65+ export type JsonStringifyResult < T > =
66+ Jsonify < T > extends InvalidJsonValue ? undefined : Jsonify < T > ;
0 commit comments