-
Notifications
You must be signed in to change notification settings - Fork 13.2k
Description
⚙ Compilation target
ES2022
⚙ Library
es2022
Missing / Incorrect Definition
ECMA-262 2011 (5.1) indicates that the value returned by a call of the JSON.stringify method may be a string or undefined. See Step 11 of the "abstract operation Str(key, holder)" outlined here in the specification.
ECMA-262 2022 (13) indicates the same. See Note #5 under the specification's JSON.stringify section.
Mozilla Developer Network documentation reiterates the same: "JSON.stringify() can return undefined when passing in "pure" values like JSON.stringify(() => {}) or JSON.stringify(undefined)".
According to the aforementioned specifications and documentation, this is the union type that includes all values that, when supplied as the first argument in a call of JSON.stringify, elicit an undefined return value: Function | Symbol | undefined.
Executing these statements in any JavaScript runtime environment confirms JavaScript engine adherence to the behavior of JSON.stringify described in the specifications and documentation:
JSON.stringify(undefined); // Returns undefined.
JSON.stringify(function() {}); // Returns undefined.
JSON.stringify(() => {}); // Returns undefined.
JSON.stringify(Symbol()); // Returns undefined.However, the JSON interface included among the TypeScript lib type definitions asserts that a call of the stringify method will return a value of type string in all cases and never an undefined value.
interface JSON {
// ...
// Neither signature includes undefined in its return type.
stringify(value: any, replacer?: (this: any, key: string, value: any) => any, space?: string | number): string;
stringify(value: any, replacer?: (number | string)[] | null, space?: string | number): string;
}The JSON interface should be modified so that its signatures for the stringify method acknowledge the cases in which the method may return undefiend as well as the cases in which it will return undefined. For example:
interface JSON {
// ...
// Will return an undefined value.
stringify(value: Function | Symbol | undefined, replacer?: (this: any, key: string, value: any) => any, space?: string | number): undefined;
// Will return either a string or undefined.
stringify(value: any, replacer?: (this: any, key: string, value: any) => any, space?: string | number): string | undefined;
// Will return an undefined value.
stringify(value: Function | Symbol | undefined, replacer?: (number | string)[] | null, space?: string | number): undefined;
// Will return either a string or undefined.
stringify(value: any, replacer?: (number | string)[] | null, space?: string | number): string | undefined;
}Sample Code
// Type of example variables reported by TypeScript compiler is string, which is inaccurate. The correct type is undefined.
const example1 = JSON.stringify(function(){});
const example2 = JSON.stringify(() => {});
const example3 = JSON.stringify(Symbol());
const example4 = JSON.stringify(undefined);
// Playground: https://www.typescriptlang.org/play?ts=5.3.0-dev.20230819#code/PTAEBUE8AcFNQPYDNSwB4EMC20A28A3DAJwEsMAjfAZ1GNmgWIBdYATUCyCGWAZQDGZaM1ACEOUvmKhStaszIA7AOYAaUAHcAFqQHbZtUkowCBAV2IZWAOgjb444vQGjmvQ6HNK2sJMfYbAChxJQVUTBx8AEZQAF5QACk+AHkAORsFZRVSJEgACiRvV1IEJXyASgBvAF8KgG4QsvD0bDxYACZ4pNSMrOMcvPzK+IA+UFqGprDRVqjYAGZu5PTMxQHcgr5ILAoEXEqp0JbI9oAWZd617M38719-JXYpoKA