DEV Community

Ivan Karbashevskyi
Ivan Karbashevskyi

Posted on

[JS/TS] Don't declare regex with flags in an object property

While I was writing the package: thiis I found one problem with regex when I tried add a new property to exist object with regex value.

When I wrote the new package's is.upperCase() method, I used a regular expression to find lowercase characters, and if found, it's an error because we want to check if the text is only uppercase, regardless of whether other characters are present, e.g. special characters.

"Bad" regex: /[a-z]/g
"Good" regex: /[a-z]/

If you are interested in why this is the logic, then write in the comments so that I write a post about it, or write about what else you are interested in knowing.

So, the problem...
The problem was only with "null" word, method passed the word as correct but it isn't, I don't why but I know how to solve the problem, let me show.

Before, I'll show you what unit tests look like.

This is unit test with cases:

    it.each([
        { value: 'a1B2c3d4e5f6g' },
        { value: 'a1B2c3d4e5f6g' },
        { value: 'inCamelCase' },
        { value: 'undefined' },
        { value: 'null' },
    ])('is.upperCase: Should false for $value', ({value}) => {
        expect(is.upperCase(value)).toBe(false);
    });
Enter fullscreen mode Exit fullscreen mode

And this is the problem, there are three screens which show you: config, method and how unit test passed cases:

  1. Config
export const isConfig = {
  useGlobalContext: true,
  error: {
    enabled: true,
  },
  regex: {
    lowerCase: /[a-z]/g, // Example how to use: !isConfig.regex.lowerCase.text('HELO WORLd') => false
  },
};
Enter fullscreen mode Exit fullscreen mode

As you can see, the "bad" regex is declare in property of config object.

  1. Method
import {isConfig} from '../config';
import {StringMethod} from './string.method';

export function UpperCaseMethod(argument: unknown): argument is string {
    if (StringMethod(argument)) {
        return !isConfig.regex.lowerCase.test(argument);
    }
    return false;
}
Enter fullscreen mode Exit fullscreen mode
  1. Unit test: passed cases

Unit test

And as you can see, we expect the result to be false, but it is true!

So, the solution to the problem:

First of all I need to check if the regex is correct, maybe I'm missing something, we can just move the regex into a method and call the test method there to test the argument and see if it works correctly.

import {isConfig} from '../config';
import {StringMethod} from './string.method';

export function UpperCaseMethod(argument: unknown): argument is string {
    if (StringMethod(argument)) {
        return !/[a-z]/g.test(argument);
    }
    return false;
}
Enter fullscreen mode Exit fullscreen mode

The result:

Unit tests

And that's what I don't know why it works correctly, the only difference is when I call the regex from the property and direction.

Next, I will try to remove the g from the regular expression and now you can see the result:

  1. Config
export const isConfig = {
  useGlobalContext: true,
  error: {
    enabled: true,
  },
  regex: {
    lowerCase: /[a-z]/, // Example how to use: !isConfig.regex.lowerCase.text('HELO WORLd') => false
  },
};
Enter fullscreen mode Exit fullscreen mode
  1. Method
import {isConfig} from '../config';
import {StringMethod} from './string.method';

export function UpperCaseMethod(argument: unknown): argument is string {
    if (StringMethod(argument)) {
        return !isConfig.regex.lowerCase.test(argument);
    }
    return false;
}
Enter fullscreen mode Exit fullscreen mode
  1. Unit test: passed cases

Unit tests

And as you can see, the result is good :)

Conclusion:
Be careful using regular expressions in object properties!

Thanks for reading the article!

Top comments (0)