Skip to content

Commit 642bb13

Browse files
authored
Jsonify: Handle unknown as JsonValue (#1206)
1 parent b5b0214 commit 642bb13

File tree

3 files changed

+28
-4
lines changed

3 files changed

+28
-4
lines changed

source/internal/keys.d.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type {IsAny} from '../is-any.d.ts';
22
import type {IsLiteral} from '../is-literal.d.ts';
3+
import type {IsUnknown} from '../is-unknown.d.ts';
34
import type {ToString} from './string.d.ts';
45

56
// Returns `never` if the key or property is not jsonable without testing whether the property is required or optional otherwise return the key.
@@ -25,7 +26,7 @@ export type FilterDefinedKeys<T extends object> = Exclude<
2526
{
2627
[Key in keyof T]: IsAny<T[Key]> extends true
2728
? Key
28-
: undefined extends T[Key]
29+
: IsUnknown<T[Key]> extends true ? Key : undefined extends T[Key]
2930
? never
3031
: T[Key] extends undefined
3132
? never

source/jsonify.d.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@ type UndefinedToNull<T> = T extends undefined ? null : T;
1818
type JsonifyList<T extends UnknownArray> = T extends readonly []
1919
? []
2020
: T extends readonly [infer F, ...infer R]
21-
? [NeverToNull<Jsonify<F>>, ...JsonifyList<R>]
21+
? [F, ...R] extends T // With TS 5.8.3, if `string[] & ['foo']`, `R` is `unknown[]` here, making the infered types neq to the original one
22+
? [NeverToNull<Jsonify<F>>, ...JsonifyList<R>]
23+
: [NeverToNull<Jsonify<F>>]
2224
: IsUnknown<T[number]> extends true
23-
? []
25+
? JsonValue[]
2426
: Array<T[number] extends NotJsonable ? null : Jsonify<UndefinedToNull<T[number]>>>;
2527

2628
type FilterJsonableKeys<T extends object> = {
@@ -119,4 +121,6 @@ export type Jsonify<T> = IsAny<T> extends true
119121
? JsonifyList<T>
120122
: T extends object
121123
? JsonifyObject<UndefinedToOptional<T>> // JsonifyObject recursive call for its children
122-
: never; // Otherwise any other non-object is removed
124+
: IsUnknown<T> extends true
125+
? JsonValue
126+
: never; // Otherwise any other non-object is removed

test-d/jsonify.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,3 +369,22 @@ expectType<typeof nestedObjectWithNameProperty>(
369369
// Regression test for https://github.com/sindresorhus/type-fest/issues/629
370370
declare const readonlyTuple: Jsonify<readonly [1, 2, 3]>;
371371
expectType<[1, 2, 3]>(readonlyTuple);
372+
373+
// `unknown` values
374+
declare const unknownValue: Jsonify<unknown>;
375+
declare const unknownArray: Jsonify<unknown[]>;
376+
declare const unknownTuple: Jsonify<[unknown, unknown]>;
377+
declare const objectWithUnknownValue: Jsonify<{key: unknown}>;
378+
expectType<JsonValue>(unknownValue);
379+
expectAssignable<Jsonify<unknown>>('foo');
380+
expectAssignable<Jsonify<unknown>>(['foo']);
381+
expectNotAssignable<Jsonify<unknown>>(new Date());
382+
expectType<JsonValue[]>(unknownArray);
383+
expectAssignable<Jsonify<unknown[]>>(['foo']);
384+
expectNotAssignable<Jsonify<unknown[]>>([new Date()]);
385+
expectType<[JsonValue, JsonValue]>(unknownTuple);
386+
expectAssignable<Jsonify<[unknown, unknown]>>(['foo', 'foo']);
387+
expectNotAssignable<Jsonify<[unknown, unknown]>>([new Date(), new Date()]);
388+
expectType<{key: JsonValue}>(objectWithUnknownValue);
389+
expectAssignable<Jsonify<{key: unknown}>>({key: []});
390+
expectNotAssignable<Jsonify<{key: unknown}>>({key: new Date()});

0 commit comments

Comments
 (0)