uhop / node-re2

node.js bindings for RE2: fast, safe alternative to backtracking regular expression engines.
Other
495 stars 53 forks source link

Typescript definitions: Cannot use buffers, only strings #99

Closed jmealo closed 3 years ago

jmealo commented 3 years ago

Since the RegExp object we extend doesn't allow buffers TypeScript will not let you use buffers with RE2 unless we change our functions in the type definition to allow for input as: Buffer | string

uhop commented 3 years ago

Do you have any proposal on how to fix it? Unfortunately I am not a user of TypeScript so I have to rely on the community. Patches welcome!

BannerBomb commented 3 years ago

Though the RegExp constructor allows passing a buffer, the built-in nodejs RegExp type definition doesn't specify that we can pass buffers. And since RE2 extends the built-in RegExp definitions it only can use what the built-in definitions have.

TypeScript will complain whether try to pass a buffer to new RegExp or new RE2 so changing it to allow buffers in one package would be inconsistent with what nodejs has.

If you wanted to fix it, you would need to change your type definitions file to something like this.

declare module 're2' {
    interface RegExpConstructor {
        new(pattern: Buffer | RegExp | string): RegExp;
        new(pattern: Buffer | string, flags?: string): RegExp;
        (pattern: Buffer | RegExp | string): RegExp;
        (pattern: Buffer | string, flags?: string): RegExp;
        readonly prototype: RegExp;

        // Non-standard extensions
        $1: string;
        $2: string;
        $3: string;
        $4: string;
        $5: string;
        $6: string;
        $7: string;
        $8: string;
        $9: string;
        lastMatch: string;
    }

    var RE2: RegExpConstructor;
    export = RE2;
}
BannerBomb commented 3 years ago

Actually, Ignore my comment above. I didn't understand what they meant the first few times I read the comment. I thought they were referring to the constructor only, but I see that RE2 implements some methods that aren't present in the built-in regex class. I'm not an expert in typescript declarations. But this is an example of what I wrote to export the custom methods for TypeScript use.

declare module 're2' {

  interface RE2MatchArray<K> extends Array<K> {
    index?: number;
    input?: K;
  }

  interface RE2ExecArray<K> extends Array<K> {
    index: number;
    input: K;
  }

  interface RE2 extends RegExp {
    exec<K extends String | Buffer>(str: K): RE2ExecArray<K> | null;

    test(str: string | Buffer): boolean;

    match<K extends String | Buffer>(str: K): RE2MatchArray<K> | null;

    replace<K extends String | Buffer>(str: K, replaceValue: string | Buffer): K;
    replace<K extends String | Buffer>(str: K, replacer: (substring: string, ...args: any[]) => string | Buffer): K;

    search(str: string | Buffer): number;

    split<K extends String | Buffer>(str: K, limit?: number): K[];
  }

  interface RE2Constructor extends RegExpConstructor {
    new(pattern: Buffer | RegExp | string): RE2;
    new(pattern: Buffer | string, flags?: string): RE2;
    (pattern: Buffer | RegExp | string): RE2;
    (pattern: Buffer | string, flags?: string): RE2;
    readonly prototype: RE2;

    unicodeWarningLevel: 'nothing' | 'warnOnce' | 'warn' | 'throw';
    getUtf8Length(value: string): number;
    getUtf16Length(value: Buffer): number;
  }

  var RE2: RE2Constructor;
  export = RE2;
}
uhop commented 3 years ago

@BannerBomb: It looks awesome! Can you do a PR for it? It would be cool if we have a way to test it somehow, so we know that it is not broken in the future.

uhop commented 3 years ago

101 was merged to the master. It will be released with 1.16.0.