I have a EventType
which should be a string with only capital letters and underscores:
type EventType = string & ('HELLO_WORLD' | 'NICE_TO_MEET_YOU' | ...)
I expect to add a regex to check the strings are containing only capital letters and underscores:
// The type `string` could be removed, because the regex indicate the type should be a string
type EventType = string & `/^[A-Z]+(?:_[A-Z]+)*$/` & ('HELLO_WORLD' | 'NICE_TO_MEET_YOU' | ...)
// This would raise a flowtype error, because `nice_to_meet_you` doesn't match the regex
type EventType = `/^[A-Z]+(?:_[A-Z]+)*$/` & ('HELLO_WORLD' | 'nice_to_meet_you' | ...)
How can I achieve this?
I'm curious why you want to add the regex check that the string has to be uppercase and underscores?
As long as all of the specific options you provide (HELLO_WORLD
, NICE_TO_MEET_YOU
, etc.) are uppercase and use underscores, then obviously only values like that will type check as EventType
.
Adding the regex will not work at the type level, because flow is a type system that operates on the basis of what it can learn from the text of the program, without actually evaluating the code.
If what you want to enforce is that when developers create new types they have to be uppercase and underscored, that seems like something to enforce with a linter rule or a comment and code review. A type system is not the right way to enforce that kind of rule.
One more thought: it's usually (though not always!) an anti-pattern to have event types just be strings like this, especially if specific events can carry specific payloads.
For example, if HELLO_WORLD
events always have a greeter
attribute that's a string
, and NICE_TO_MEET_YOU
events have a time
that's a Time
, it would be best to represent the exact details of that with types, such as:
type EventType =
{ type: "HELLO_WORLD", greeter: string }
| { type: "NICE_TO_MEET_YOU", date: Date };
@asolove How can I set the linter rule to check the type being uppercase and underscored?
Sorry, I honestly don't know. I tried googling for an eslint rule to do it, but didn't find anything. In the codebases I've worked in, we've just done code review to ensure this.
Unless there is something Flow can help with, I think we can close this issue.
@asolove I think this could be done by flowtype check. It is a feature request.
For example, I could make a variable only be valid for HTTP/HTTPS URL by regex with flowtype:
type HTTP_URL = regex`{{HTTP RegExp rule here}}`;
const resourceURL: HTTP_URL = 'http://...';
There are so many places needs to be check whether a string is a valid format in my project.
Regardless if it's a good idea or not, I think a big difficulty here is that flow isn't written in Javascript, but OCaml. So if we wanted regex checking in flow, then flow either needs to implement a full Javascript regex engine, or we need to use OCaml syntax (like in the .flowconfig
). I think the latter is not an option, and the former is likely a huge undertaking.
OCaml's regex engine is hot garbage.
There really is no way Flow can tell during type-checking time whether strings at runtime will match a certain regex.
So since you need to have code at runtime to check values and see if they are valid, a good pattern is to write a function that takes in a string and returns an opaque type marking some property of the string. If you want a type for URLs that are definitely valid, you could do:
opaque type URL: string = string;
function parseUrl(url: string): ?URL {
if(/* some code to test if it's a url */ true) {
return url;
} else {
return null;
}
}
Now code outside of this module can accept and return URL
-typed objects and trust that they really are valid URLs, because only this one function can create objects of that type, and it checks that they are valid.
@asolove I need to check at compile/transpile time, not runtime.
type HTTP_URL = regex`{{HTTP RegExp rule here}}`;
const resourceURL: HTTP_URL = 'http://...'; // check this before transpiling
I agree this would be a useful feature. I have some hex color strings in my app, and it would be nice if I could set a regex to validate that the strings must match the format: /^#[0-9a-fA-F]{6}$/
. (At compile time.)
I would also like to see this! We have a number of ids that need to be correctly formatted (imagine something like "source
Hi @asolove, @vkurchatkin and @xareelee
There are ways to make flow more powerful... but
I believe that you want keep it predictable... that may be costly:
Regular Expressions Are Not Regular, they may eat the Universe without giving result,
however it can be decided if the regular expression needs backtracking or not and this is safe
Like constants are used in sets 'aaa' | 'bbb' | 'ccc'
, (subset without backtracking of) regular expressions can be used between:
See this expression:
"ONLY"
⊂ ("ONLY" | "OTHER")
⊂ $CharSet<"EHLNORTY">
⊂ $Match</^[_A-Z]{4,5}$/>
⊂ string
⊂ mixed
⊂ *
⊂ any
'ONLY'
will match all this types in flow"OTHER"
match all except first."NORTY"
will match $CharSet<"EHLNORTY">
…"ONLY_ONE_NORTY"
will match regular string predicate $Match</^[_A-Z]{4,5}$/>
← all about this — type $Match
, this does not exists yet :smiling_imp:"one norty and the others"
, 123
, {a: 1}
, …This is really not much different from what is flow actually doing with all the types, but may be much more challenging.
However, there is very similar (may be even implementation base), compare this legacy code with the new one: type RegExp$flags = $CharSet<"gimsuy">
OCaml's regex engine is hot garbage.
Ugh yes, having yarn link
-ed a local package source into my node_modules, Flow is walking into it, and trying to type-check the test code, which isn't working because the root project has some global libdefs for test()
that don't apply to these tests.
Trying to write an OCaml regex for "ignore everything in this folder except the contents of lib/
is proving frustrating without the ability to use (?!lib/)
as a pattern. And you can't explicitly include lib/
and exclude the rest because Flow processes ignores after includes and they supercede.
The alternative is ignore the whole lib and lose it's typedefs, or monkey about "publishing" it to a folder and linking to that instead, which will probably get unlinked whenever I use yarn next.
Most helpful comment
I agree this would be a useful feature. I have some hex color strings in my app, and it would be nice if I could set a regex to validate that the strings must match the format:
/^#[0-9a-fA-F]{6}$/
. (At compile time.)