type-fest icon indicating copy to clipboard operation
type-fest copied to clipboard

Jsonify does not look deeper than one `toJSON` level

Open MGibson1 opened this issue 1 year ago • 0 comments

I have a type to Jsonify, similar to this:

class Top {
  override: ArrayBuffer;
  inner: Inner;

  toJSON() {
    const stringOverride = "override";
    return {
      override: stringOverride,
      inner: this.inner,
    };
  }
}

class Inner {
  buffer: ArrayBuffer;

  toJSON() {
    const stringBuffer = "buffer";
    return {
      buffer: stringBuffer,
    };
  }
}

In this example, Jsonify<Top> will return never, because Inner is not a valid JsonValue, however, Jsonify<Inner> is a JsonValue. The Jsonify<T> type will inspect T for a toJSON method, but mandates that the return type be a valid JsonValue.

The relevant section of Jsonify is

...
	? 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
...

I would like to expand the final never above to mimic the recursive Jsonify call below it to do the same deep Jsonify process even if a toJSON method is defined. This is more similar to how JSON.stringify works, which will recursively call toJSON on each property that defines it.

MGibson1 avatar Sep 19 '22 13:09 MGibson1