2

As an embedded software engineer used to strictly-typed languages, I was compelled to use Flow (https://flow.org) when writing an experimental utility in JavaScript.

About 10 minutes into writing code with JS+Flow, Flow ('flow-bin' binary) gave me the following error:

Cannot call string.trim().replaceAll because property replaceAll (did you mean replace?) is missing in String [1].

with regards to the following (Flow-annotated) code:

static sanitizeString(string : string) : string {
    return string.trim().replaceAll(/(?:\s+|\.+)/g, "");
}

Flow tells me that it can not find the (fairly-widely implemented) string.prototype.replaceAll(...) function in (what seems to be a) "symbolic" definitions file: tmp/flow/flowlib_1fa18dde633e97c7_501/core.js

Which begs the question:

Are Flow users solely at the mercy of the provisioned definitions file when it comes to using (widely-implemented) methods defined by ECMAScript standards (or proposals/drafts for that matter, given the fast-paced nature of browsers' implementation of ECMAScript)?

Do I have to modify the definitions file (core.js) to resolve this problems?

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
MindMason
  • 23
  • 4
  • `replaceAll` might be "widely implemented" but it's still quite new in terms of when it was actually introduced. IIRC, it was an ES2020 addition which is still quite recent. I'm not quite familiar with Flow but perhaps you can change the supported version. – VLAZ Dec 18 '20 at 15:20
  • 1
    Actually I double checked - `replaceAll` was approved in this year but it's scheduled for adding to the ES2021 standard. So, there you go. – VLAZ Dec 18 '20 at 15:23
  • @VLAZ Thanks. Seems like there really is only one 'core.js' as the "source of truth" for Flow (readers more familiar with Flow could correct me if I'm wrong). Moved over to TypeScript since 'esnext' option is up to date with the proposals (as Samuli Hakoniemi also pointed out below). As for replaceAll(), it has been at "the final stage" (Stage 4) of the TC39 process for the last 6 months: https://github.com/tc39/proposal-string-replaceall . – MindMason Dec 18 '20 at 15:50
  • Yes, it was approved in June, it is scheduled to be in the *next* release of the standard, ES2021. So, technically it's not a standard yet. It is going to be, though. – VLAZ Dec 18 '20 at 15:51

2 Answers2

2

First of all, I don't have direct answer to this question, but I'll try to elaborate the problem a bit.

But this is rather interesting. It truly throws that error: Flow Example

Now, it gets even more interesting since TypeScript throws the same error: TS Example

However, TS is more robust with the error message:

Property 'replaceAll' does not exist on type 'string'. Do you need to change your target library? Try changing the lib compiler option to 'esnext' or later.

Hence, I suggest you to follow that advice and switch flow compiler to follow different set of rules (in .flowconfig I guess?).

Samuli Hakoniemi
  • 18,740
  • 1
  • 61
  • 74
  • 1
    I switched over to TypeScript, since it seems that Flow doesn't provide options with regards to which version of ECMAScript to use – Seems like there really only is one 'core.js' at the "source of truth" for Flow. TypeScript with "esnext" seems to be keeping up with the browsers! – MindMason Dec 18 '20 at 15:38
1

I think we need to strive to contextualize this question a bit before it can really be considered answered.

Flow provides a base set of types as a good starting point for most use cases. These are regularly updated, but not really as part of a methodical process. Users often open PRs against flow to update the provided libdefs with pieces they are interested in using, and that's probably the most common way these updates occur right now. Changes to the core types are usually very simple and make good "first PRs". It's also worthwhile to note that flow has far fewer incoming PRs than typescript.

So the reality on the ground ends up being that flow's provided types are not always up to date with every piece of the most recent spec. The question becomes, how is one expected to manage this situation?

One option is to stop using the provided types. Flow has a config option:

no_flowlib (boolean)

Flow has builtin library definitions. Setting this to true will tell Flow to ignore the builtin library definitions.

The default value is false.

By setting this to true we'll no longer get any of flow's provided types. This allows us to use only the types we specify. A common practice is to toggle this to true, copy flow's provided types into the project's local libdefs, and make modifications to them in-place. This would allow us to get all the benefits of using the provided types while also being able to make any necessary modifications. The main downside is that the types must now be updated manually whenever upgrading the flow version.

The other option, of course, is to just open a PR. Flow releases fairly rapidly and reliably, and changes to the provided libdefs are usually merged quickly.

I'll withhold comment on how satisfactory this state of affairs may or may not be, but if anybody is facing these concerns then hopefully this is all the information you need in order to formulate solutions.

Lyle Underwood
  • 1,304
  • 7
  • 12