diff --git a/source/jsonify.d.ts b/source/jsonify.d.ts index d75d4db04..d7c6404ab 100644 --- a/source/jsonify.d.ts +++ b/source/jsonify.d.ts @@ -67,25 +67,24 @@ type Jsonify = // Note: The use of tuples in this first condition side-steps distributive conditional types // (see https://github.com/microsoft/TypeScript/issues/29368#issuecomment-453529532) [Extract] extends [never] - ? T extends PositiveInfinity | NegativeInfinity ? null - : T extends JsonPrimitive - ? T // Primitive is acceptable - : T extends Number ? number - : T extends String ? string - : T extends Boolean ? boolean - : T extends Map | Set ? {} - : T extends TypedArray ? Record - : T extends Array - ? Array> // It's an array: recursive call for its children - : T extends object - ? T extends {toJSON(): infer J} - ? (() => J) extends (() => JsonValue) // Is J assignable to JsonValue? - ? J // Then T is Jsonable and its Jsonable value is J - : never // Not Jsonable because its toJSON() method does not return JsonValue - : {[P in keyof T as P extends symbol - ? never - : T[P] extends NotJsonable - ? never - : P]: Jsonify[P]>} // It's an object: recursive call for its children - : never // Otherwise any other non-object is removed + ? T extends PositiveInfinity | NegativeInfinity ? null + : T extends JsonPrimitive ? T // Primitive is acceptable + : T extends object + // Any object with toJSON is special case + ? T extends {toJSON(): infer J} ? (() => J) extends (() => JsonValue) // Is J assignable to JsonValue? + ? J // Then T is Jsonable and its Jsonable value is J + : never // Not Jsonable because its toJSON() method does not return JsonValue + // Instanced primitives are objects + : T extends Number ? number + : T extends String ? string + : T extends Boolean ? boolean + : T extends Map | Set ? {} + : T extends TypedArray ? Record + : T extends any[] + ? {[I in keyof T]: T[I] extends NotJsonable ? null : Jsonify} + : {[P in keyof T as P extends symbol ? never + : T[P] extends NotJsonable ? never + : P + ]: Jsonify[P]>} // Recursive call for its children + : never // Otherwise any other non-object is removed : never; // Otherwise non-JSONable type union was found not empty diff --git a/test-d/jsonify.ts b/test-d/jsonify.ts index c8309a311..e972a8325 100644 --- a/test-d/jsonify.ts +++ b/test-d/jsonify.ts @@ -186,6 +186,12 @@ expectType(stringJson); declare const booleanJson: Jsonify; expectType(booleanJson); +declare const tupleJson: Jsonify<[string, Date]>; +expectType<[string, string]>(tupleJson); + +declare const tupleRestJson: Jsonify<[string, ...Date[]]>; +expectType<[string, ...string[]]>(tupleRestJson); + // BigInt fails JSON.stringify declare const bigInt: Jsonify; expectType(bigInt);