When you use alternation (the character |
), the regex will try the alternatives from left to right, until find one that fits.
In this case, if the input is the string datetime
, regex cannot find the match the first 16 alternatives (including the fourth - datetime(-local)$
- looking for something that ends with datetime-local
, and see that parentheses make no difference here).
In alternative 17 (time$
) she finds a match, since this passage means "ends with time
", and datetime
matches this. That’s why your regex returns true
for the string datetime
.
Your solution worked because you added ^
, then the alternative "begins with datetime-local
" now gives match - and datetime
no more match because you’ve changed time$
(ends with time
) for ^time
(begins with time
).
But anyway, if you want to check if a string matches exactly one of the names that are in regex, you can change it to:
const regExpTypes = new RegExp(
"^(button|color|date|datetime-local|email|file|hidden|image|month|password|radio|range|reset|search|submit|tel|text|time|url|week)$"
);
console.log(regExpTypes.test("datetime")); // false
console.log(regExpTypes.test("datetime-local")); // true
This regex has the markers ^
and $
, which are respectively the beginning and end of the string. Then between them there is a toggle with all the alternatives that you want to capture.
Note that all the alternatives are in parentheses, because it makes a difference.
If I do, for example, ^button|color$
, that means "start with button
, or ends with color
" - and if it starts with button
, may even have more after; if it ends with color
, may have more things before - see:
const regExpTypes = /^button|color$/;
console.log(regExpTypes.test("button")); // true
console.log(regExpTypes.test("button123")); // true
console.log(regExpTypes.test("color")); // true
console.log(regExpTypes.test("123color")); // true
If I ever put ^(button|color)$
, that means "string start", followed by button
or color
, followed by the end of the string. That is, the string can only have what is in the alternatives, no more characters, no less (see).
const regExpTypes = /^(button|color)$/;
console.log(regExpTypes.test("button")); // true
console.log(regExpTypes.test("button123")); // false
console.log(regExpTypes.test("color")); // true
console.log(regExpTypes.test("123color")); // false
So if you want the string to be exactly one of the alternatives, use ^(alternativas)$
.
You can simplify it a little bit more:
const regExpTypes = new RegExp(
"^(button|color|date(time-local)?|email|file|hidden|image|month|password|ra(dio|nge)|reset|search|submit|te(l|xt)|time|url|week)$"
);
console.log(regExpTypes.test("datetime")); // false
console.log(regExpTypes.test("datetime-local")); // true
I made some modifications:
date(time-local)?
: the stretch time-local
is in parentheses, and the ?
soon after make it optional. So this stretch takes date
or datetime-local
(but not datetime
)
ra(dio|nge)
: picks up the strings radio
or range
te(l|xt)
: picks up the strings tel
or text
Regex-free
But for this case it might be simpler to have an array with valid alternatives, and then check if the string is in this array, using the method includes
:
const validos = ['button', 'color', 'date', 'datetime-local', 'email',
'file', 'hidden', 'image', 'month', 'password', 'radio',
'range', 'reset', 'search', 'submit', 'tel', 'text', 'time', 'url', 'week'];
console.log(validos.includes("datetime")); // false
console.log(validos.includes("datetime-local")); // true