Skip to content

Commit

Permalink
Jsonify: Fix handling of arrays (#673)
Browse files Browse the repository at this point in the history
  • Loading branch information
Emiyaaaaa committed Sep 30, 2023
1 parent 493013b commit 025f6e9
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 18 deletions.
26 changes: 13 additions & 13 deletions source/jsonify.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 unknown[]> = T extends [infer F, ...infer R]
? IsNever<F> extends true
? FilterNonNever<R>
: [F, ...FilterNonNever<R>]
: IsNever<T[number]> extends true
? []
: T;
type NeverToNull<T> = IsNever<T> extends true ? null : T;

// Handles tuples and arrays
type JsonifyList<T extends unknown[]> = T extends [infer F, ...infer R]
? FilterNonNever<[Jsonify<F>, ...JsonifyList<R>]>
: Array<Jsonify<T[number]>>;
type JsonifyList<T extends unknown[]> = T extends []
? []
: T extends [infer F, ...infer R]
? [NeverToNull<Jsonify<F>>, ...JsonifyList<R>]
: IsUnknown<T[number]> extends true
? []
: Array<T[number] extends NotJsonable ? null : Jsonify<T[number]>>;

type FilterJsonableKeys<T extends object> = {
[Key in keyof T]: T[Key] extends NotJsonable ? never : Key;
Expand Down Expand Up @@ -116,10 +116,10 @@ export type Jsonify<T> = IsAny<T> extends true
: Jsonify<J> // Maybe if we look a level deeper we'll find a JsonValue
: T extends []
? []
: T extends [unknown, ...unknown[]]
: T extends unknown[]
? JsonifyList<T>
: T extends ReadonlyArray<infer U>
? Array<U extends NotJsonable ? null : Jsonify<U>>
: T extends readonly unknown[]
? JsonifyList<WritableDeep<T>>
: T extends object
? JsonifyObject<UndefinedToOptional<T>> // JsonifyObject recursive call for its children
: never; // Otherwise any other non-object is removed
17 changes: 12 additions & 5 deletions test-d/jsonify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<string[] & ['some value']>;
expectType<['some value']>(tupleStringJson);

Expand Down Expand Up @@ -334,10 +337,14 @@ declare const nestedObjectWithNameProperty: {
name: string;
};
};
declare const jsonifiedNestedObjectWithNameProperty: Jsonify<typeof nestedObjectWithNameProperty>;
declare const jsonifiedNestedObjectWithNameProperty: Jsonify<
typeof nestedObjectWithNameProperty
>;

expectType<typeof nestedObjectWithNameProperty>(jsonifiedNestedObjectWithNameProperty);
expectType<typeof nestedObjectWithNameProperty>(
jsonifiedNestedObjectWithNameProperty,
);

/// #629
// declare const readonlyTuple: Jsonify<readonly [1, 2, 3]>;
// expectType<readonly [1, 2, 3]>(readonlyTuple);
// Regression test for https://github.com/sindresorhus/type-fest/issues/629
declare const readonlyTuple: Jsonify<readonly [1, 2, 3]>;
expectType<[1, 2, 3]>(readonlyTuple);

0 comments on commit 025f6e9

Please sign in to comment.