From 025f6e9db5db7ae3ee5697595fb7eb0fce1e3998 Mon Sep 17 00:00:00 2001 From: Emiya <2914034404@qq.com> Date: Sat, 30 Sep 2023 22:32:23 +0800 Subject: [PATCH] `Jsonify`: Fix handling of arrays (#673) --- source/jsonify.d.ts | 26 +++++++++++++------------- test-d/jsonify.ts | 17 ++++++++++++----- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/source/jsonify.d.ts b/source/jsonify.d.ts index 1894ee250..d429e2ddc 100644 --- a/source/jsonify.d.ts +++ b/source/jsonify.d.ts @@ -3,24 +3,24 @@ import type {EmptyObject} from './empty-object'; import type {UndefinedToOptional} from './internal'; import type {IsAny} from './is-any'; import type {IsNever} from './is-never'; +import type {IsUnknown} from './is-unknown'; import type {NegativeInfinity, PositiveInfinity} from './numeric'; import type {TypedArray} from './typed-array'; +import type {WritableDeep} from './writable-deep'; // Note: The return value has to be `any` and not `unknown` so it can match `void`. type NotJsonable = ((...arguments_: any[]) => any) | undefined | symbol; -type FilterNonNever = T extends [infer F, ...infer R] - ? IsNever extends true - ? FilterNonNever - : [F, ...FilterNonNever] - : IsNever extends true - ? [] - : T; +type NeverToNull = IsNever extends true ? null : T; // Handles tuples and arrays -type JsonifyList = T extends [infer F, ...infer R] - ? FilterNonNever<[Jsonify, ...JsonifyList]> - : Array>; +type JsonifyList = T extends [] + ? [] + : T extends [infer F, ...infer R] + ? [NeverToNull>, ...JsonifyList] + : IsUnknown extends true + ? [] + : Array>; type FilterJsonableKeys = { [Key in keyof T]: T[Key] extends NotJsonable ? never : Key; @@ -116,10 +116,10 @@ export type Jsonify = IsAny extends true : Jsonify // Maybe if we look a level deeper we'll find a JsonValue : T extends [] ? [] - : T extends [unknown, ...unknown[]] + : T extends unknown[] ? JsonifyList - : T extends ReadonlyArray - ? Array> + : T extends readonly unknown[] + ? JsonifyList> : T extends object ? JsonifyObject> // JsonifyObject recursive call for its children : never; // Otherwise any other non-object is removed diff --git a/test-d/jsonify.ts b/test-d/jsonify.ts index b642a2a66..2c263dd1f 100644 --- a/test-d/jsonify.ts +++ b/test-d/jsonify.ts @@ -222,6 +222,9 @@ expectType<[string, string]>(tupleJson); declare const tupleRestJson: Jsonify<[string, ...Date[]]>; expectType<[string, ...string[]]>(tupleRestJson); +declare const mixTupleJson: Jsonify<['1', (_: any) => void, 2]>; +expectType<['1', null, 2]>(mixTupleJson); + declare const tupleStringJson: Jsonify; expectType<['some value']>(tupleStringJson); @@ -334,10 +337,14 @@ declare const nestedObjectWithNameProperty: { name: string; }; }; -declare const jsonifiedNestedObjectWithNameProperty: Jsonify; +declare const jsonifiedNestedObjectWithNameProperty: Jsonify< + typeof nestedObjectWithNameProperty +>; -expectType(jsonifiedNestedObjectWithNameProperty); +expectType( + jsonifiedNestedObjectWithNameProperty, +); -/// #629 -// declare const readonlyTuple: Jsonify; -// expectType(readonlyTuple); +// Regression test for https://github.com/sindresorhus/type-fest/issues/629 +declare const readonlyTuple: Jsonify; +expectType<[1, 2, 3]>(readonlyTuple);