1

I'm working on a polyfill that extends the behavior of the JSON.parse() function by adding an optional third argument to the reviver callback function.

The polyfill should be imported like this for the end users:

import 'my-polyfill';

The JSON.parse() is defined in the node_modules/typescript/lib/lib.es5.d.ts like this:

// lib.es5.d.ts

interface JSON {

  // …

  parse(
    text: string,
    reviver?: (this: any, key: string, value: any) => any
  ): any;

  // …

}

How do I override this definition, so when the polyfill is installed/imported my definition is used instead? E.g.:

interface ContextType {
  // …
}

interface JSON {

  parse<Type = any>(
    text: string,
    reviver?: (
      key: string,
      value: any,
      context?: ContextType
    ) => any

  ): Type;

}
Slava Fomin II
  • 26,865
  • 29
  • 124
  • 202
  • If you're writing a polyfill, shouldn't it already exist in *lib.esnext.d.ts*? – Bergi Jan 14 '23 at 23:50
  • @Bergi good idea, but no, it's not. – Slava Fomin II Jan 15 '23 at 00:49
  • You can't, but you can remove that library from compilation and use your own modified version of it instead. I previously answered a question about a similar scenario [here](https://stackoverflow.com/a/69539181/438273) that should be of help. – jsejcksn Jan 15 '23 at 01:07
  • 1
    Just to clarify terminology, the term "polyfill" is used when you are implementing a feature that is already, or is strongly suspected to become, part of standard Javascript. Simply modifying a built-in function for your own needs is *not* a polyfill (and is generally discouraged). – Guillaume Brunerie Jan 16 '23 at 07:54
  • 1
    @GuillaumeBrunerie I AM writing a polyfill for TC39 Stage-3 proposal, so I guess it should be a valid reason to override the basic types :) – Slava Fomin II Jan 16 '23 at 08:46
  • @SlavaFominII Good to know, everything is good then :) Maybe you should make a pull request against Typescript, then, instead of a separate package? – Guillaume Brunerie Jan 16 '23 at 09:40
  • @GuillaumeBrunerie this is a good idea, I will see if this would be viable. Thanks. – Slava Fomin II Jan 20 '23 at 23:39

1 Answers1

1

You could create declarations file and name it, for example, as polyfill.d.ts. Then, you should use standard way of extending global types as follows:

declare global {
  interface JSON {
    // Here, you should write your own implementation of `parse` function.
    parse(variable: string): void;
  }
}

export {};

export is required by TypeScript and you can learn more about it in this answer and its comments.

Don't forget, that when you create a separate library, this file should exist in final build directory. So, when some user installs your package and imports it, file polyfill.d.ts would be automatically applied by TypeScript.

I am not sure, that you are able to make TypeScript transfer declarations file (.d.ts) with its own functionality. To do this, we should use some hack, described here. We should name file not polyfill.d.ts, but polyfill.ts and import it in library's index.ts file, so it would be imported by TypeScript and transferred to build directory.