Repository: blitz-js/superjson
Pull request #7 (2020-07-14 13:56:49)

Add NaN and +/-Infinity tests
- NaN and Infinity are of type `number` but aren't naturally serializable as JSON



Patch:
diff --git a/src/types.ts b/src/types.ts
index c75e27b..098f0f8 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -37,4 +37,12 @@ export interface SuperJSONResult {
   meta: null | JSONType | Record<string, JSONType>;
 }
 
-export type JSONType = 'undefined' | 'bigint' | 'Date' | 'set' | 'regexp';
+export type JSONType =
+  | 'undefined'
+  | 'bigint'
+  | 'Date'
+  | 'NaN'
+  | 'Infinity'
+  | '-Infinity'
+  | 'set'
+  | 'regexp';
diff --git a/src/utils/isJSONPrimitive.ts b/src/utils/isJSONPrimitive.ts
index a99327d..6fb0573 100644
--- a/src/utils/isJSONPrimitive.ts
+++ b/src/utils/isJSONPrimitive.ts
@@ -3,4 +3,7 @@ import is from '@sindresorhus/is';
 export const isJSONPrimitive = (
   value: any
 ): value is string | number | boolean | null =>
-  is.string(value) || is.number(value) || is.boolean(value) || is.null_(value);
+  is.string(value) ||
+  (is.number(value) && !is.infinite(value)) ||
+  is.boolean(value) ||
+  is.null_(value);
diff --git a/src/utils/isSerializable.ts b/src/utils/isSerializable.ts
index 023c886..cb040bc 100644
--- a/src/utils/isSerializable.ts
+++ b/src/utils/isSerializable.ts
@@ -5,5 +5,7 @@ export const isSerializable = (value: any): value is SerializableJSONValue =>
   is.undefined(value) ||
   is.bigint(value) ||
   is.date(value) ||
+  is.nan(value) ||
+  is.infinite(value) ||
   is.set(value) ||
   is.regExp(value);
diff --git a/src/utils/transformer.ts b/src/utils/transformer.ts
index f26e733..ea4b184 100644
--- a/src/utils/transformer.ts
+++ b/src/utils/transformer.ts
@@ -19,6 +19,16 @@ export const transformValue = (
       value: value.toISOString(),
       type: 'Date',
     };
+  } else if (is.nan(value)) {
+    return {
+      value: undefined,
+      type: 'NaN',
+    };
+  } else if (is.infinite(value)) {
+    return {
+      value: undefined,
+      type: value > 0 ? 'Infinity' : '-Infinity',
+    };
   } else if (is.set(value)) {
     return {
       value: Array.from(value) as any[],
@@ -42,6 +52,12 @@ export const untransformValue = (json: JSONValue, type: JSONType) => {
       return undefined;
     case 'Date':
       return new Date(json as string);
+    case 'NaN':
+      return 0 / 0;
+    case 'Infinity':
+      return 1 / 0;
+    case '-Infinity':
+      return -1 / 0;
     case 'set':
       return new Set(json as unknown[]);
     case 'regexp': {


Test patch:
diff --git a/test/index.test.ts b/test/index.test.ts
index 85ae28c..3b9891d 100644
--- a/test/index.test.ts
+++ b/test/index.test.ts
@@ -58,6 +58,24 @@ describe('serialize works for', () => {
     });
   });
 
+  it('NaN', () => {
+    expect(serialize(NaN)).toStrictEqual({ json: undefined, meta: 'NaN' });
+  });
+
+  it('Infinity', () => {
+    expect(serialize(Infinity)).toStrictEqual({
+      json: undefined,
+      meta: 'Infinity',
+    });
+  });
+
+  it('-Infinity', () => {
+    expect(serialize(-Infinity)).toStrictEqual({
+      json: undefined,
+      meta: '-Infinity',
+    });
+  });
+
   /*
     Basic objects
   */
@@ -204,6 +222,33 @@ describe('deserialize works for', () => {
     ).toStrictEqual(BigInt(Number.MAX_VALUE) + BigInt(10));
   });
 
+  it('NaN', () => {
+    expect(
+      deserialize({
+        json: undefined,
+        meta: 'NaN',
+      })
+    ).toStrictEqual(NaN);
+  });
+
+  it('Infinity', () => {
+    expect(
+      deserialize({
+        json: undefined,
+        meta: 'Infinity',
+      })
+    ).toStrictEqual(Infinity);
+  });
+
+  it('-Infinity', () => {
+    expect(
+      deserialize({
+        json: undefined,
+        meta: '-Infinity',
+      })
+    ).toStrictEqual(-Infinity);
+  });
+
   /*
     Basic objects
   */