<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Flow - Medium]]></title>
        <description><![CDATA[Flow is a typed dialect of JavaScript. Check out the docs at https://flow.org/ - Medium]]></description>
        <link>https://medium.com/flow-type?source=rss----ab067ae921ed---4</link>
        <image>
            <url>https://cdn-images-1.medium.com/proxy/1*TGH72Nnw24QL3iV9IOm4VA.png</url>
            <title>Flow - Medium</title>
            <link>https://medium.com/flow-type?source=rss----ab067ae921ed---4</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Wed, 24 Jun 2026 11:50:49 GMT</lastBuildDate>
        <atom:link href="https://medium.com/feed/flow-type" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[JavaScript Pattern Matching with Flow]]></title>
            <link>https://medium.com/flow-type/javascript-pattern-matching-with-flow-a2a143108897?source=rss----ab067ae921ed---4</link>
            <guid isPermaLink="false">https://medium.com/p/a2a143108897</guid>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[typescript]]></category>
            <category><![CDATA[flowtype]]></category>
            <dc:creator><![CDATA[George Zahariev]]></dc:creator>
            <pubDate>Tue, 09 Jun 2026 17:06:35 GMT</pubDate>
            <atom:updated>2026-06-09T21:27:51.594Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*qAdxb8yhpqxa73gnpxi-vQ.png" /></figure><p>Branching in JavaScript can be a pain. switch? Full of footguns. Nested conditional ternary expressions? Unreadable. Initializing a let over a bunch of if/else? Verbose. That weird chain of &amp;&amp; in your JSX? No thanks. And none of these handle complex structures or check if you handled every case.</p><p>If you haven’t looked at <a href="https://flow.org/">Flow</a> recently: its syntax has grown so close to TypeScript that most code is hard to tell apart (here’s a <a href="https://flow.org/en/docs/flow-vs-typescript">side-by-side for TypeScript users</a>). But Flow isn’t just type annotations: it adds first-class language features built for safety.</p><p>match expressions and statements are the newest. They branch on a value: the first pattern that matches maps to a result. match destructures as it matches, and it&#39;s exhaustively checked. If you forget a case of the input, Flow tells you what&#39;s missing and prevents that bug from hitting production.</p><h3>An expression, not just a statement</h3><p>switch is a statement. It can&#39;t produce a value, so the moment you want one you&#39;re back to a let you assign across cases, or a conditional ternary chain. match is both a statement and an expression. As an expression, it gives you the value directly:</p><pre>const description = match (action) {<br>  {type: &#39;add&#39;, const text} =&gt; `Add: ${text}`,<br>  {type: &#39;toggle&#39;, const id} =&gt; `Toggle ${id}`,<br>  {type: &#39;remove&#39;, const id} =&gt; `Remove ${id}`,<br>};</pre><p>Each pattern matches <em>and</em> extracts values at the same time. {type: &#39;add&#39;, const text} checks that type is &#39;add&#39; and binds text in one step, no separate destructuring.</p><h3>Exhaustively checked by default</h3><p>Drop a case and Flow tells you exactly which one is missing:</p><pre>type Action =<br>  | {type: &#39;add&#39;, text: string}<br>  | {type: &#39;toggle&#39;, id: string}<br>  | {type: &#39;remove&#39;, id: string};<br>declare const action: Action;<br><br>const description = match (action) {<br>  {type: &#39;add&#39;, const text} =&gt; `Add: ${text}`,<br>  {type: &#39;toggle&#39;, const id} =&gt; `Toggle ${id}`,<br>  // ERROR: add the missing pattern `{type: &#39;remove&#39;, id: _}`<br>};</pre><p>Add a new variant to Action during a later refactor, and every match that doesn&#39;t handle it lights up. Delete a variant and Flow points at the now-dead patterns to remove.</p><h3>A better switch</h3><p>When you want a statement, match is a switch without the footguns. Cases don&#39;t fall through, so there&#39;s no break to forget. Each case is its own block, so use those lets and consts without worry. And just like the expression form, it&#39;s exhaustively checked.</p><pre>// Before<br>switch (command) {<br>  case &#39;delete&#39;:<br>  case &#39;remove&#39;:<br>    data.pop();<br>    break;<br>  case &#39;add&#39;:<br>    data.push(1);<br>    break;<br>  default:<br>    show(data);<br>}<br>// After<br>match (command) {<br>  &#39;delete&#39; | &#39;remove&#39; =&gt; {<br>    data.pop();<br>  }<br>  &#39;add&#39; =&gt; {<br>    data.push(1);<br>  }<br>  _ =&gt; {<br>    show(data);<br>  }<br>}</pre><p>&#39;delete&#39; | &#39;remove&#39; is an <em>or-pattern</em>: one block for several patterns. _ is the wildcard, matching anything left over.</p><h3>Patterns go deep</h3><p>Patterns aren’t limited to single values. They reach into nested objects and arrays, binding as they go:</p><pre>const name = match (entity) {<br>  {type: &#39;user&#39;, details: {const name}} =&gt; name,<br>  {type: &#39;page&#39;, pageInfo: {const pageName}} =&gt; pageName,<br>  {type: &#39;employee&#39;, const preferredName} =&gt; preferredName,<br>};</pre><p>They match arrays and tuples by shape, so you can branch on several values at once. Exhaustiveness works here too: leave a combination out and Flow tells you the fix.</p><pre>const style = match ([align, position]) {<br>  [&#39;start&#39;, &#39;above&#39;] =&gt; styles.alignTopLeft,<br>  [&#39;start&#39;, &#39;below&#39;] =&gt; styles.alignBottomLeft,<br>  [&#39;end&#39;, &#39;above&#39;] =&gt; styles.alignTopRight,<br>  // ERROR: add the missing pattern `[&#39;end&#39;, &#39;below&#39;]`<br>};</pre><h3>Conditional React rendering, finally readable</h3><p>Conditional rendering in React is exactly what match expressions are for:</p><pre>function Page({tab}: {tab: &#39;home&#39; | &#39;details&#39; | &#39;settings&#39;}) {<br>  return match (tab) {<br>    &#39;home&#39; =&gt; &lt;Home /&gt;,<br>    &#39;details&#39; =&gt; &lt;DetailsPane /&gt;,<br>    &#39;settings&#39; =&gt; &lt;Settings /&gt;,<br>  };<br>}</pre><p>No ternary nest, no stray &amp;&amp;, and if a new tab is added to the union, Flow makes you handle it.</p><h3>Try it</h3><p>match brings exhaustiveness, destructuring, and readable branching together in one construct. It&#39;s the kind of language-level feature Flow exists to add: not just describing the JavaScript you already write, but giving you better JavaScript to write.</p><p>It’s available now.</p><ul><li>Read the <a href="https://flow.org/en/docs/match">docs on </a><a href="https://flow.org/en/docs/match">match</a>, including if guards, as patterns, and more</li><li>Moving off switch? See the <a href="https://flow.org/en/docs/match/migration/">migration guide</a></li><li>Coming from TypeScript? See <a href="https://flow.org/en/docs/flow-vs-typescript">Flow for TypeScript Users</a></li><li>Try it live in the <a href="https://flow.org/try">Flow playground</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a2a143108897" width="1" height="1" alt=""><hr><p><a href="https://medium.com/flow-type/javascript-pattern-matching-with-flow-a2a143108897">JavaScript Pattern Matching with Flow</a> was originally published in <a href="https://medium.com/flow-type">Flow</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Flow for TypeScript Users in 2026]]></title>
            <link>https://medium.com/flow-type/flow-for-typescript-users-in-2026-ad07ac0a2d92?source=rss----ab067ae921ed---4</link>
            <guid isPermaLink="false">https://medium.com/p/ad07ac0a2d92</guid>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[flowtype]]></category>
            <category><![CDATA[react]]></category>
            <category><![CDATA[typescript]]></category>
            <dc:creator><![CDATA[George Zahariev]]></dc:creator>
            <pubDate>Thu, 04 Jun 2026 23:30:49 GMT</pubDate>
            <atom:updated>2026-06-16T19:24:22.548Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*oer_57DM098C7FN19myK1w.png" /></figure><p>In 2026 <a href="https://flow.org/">Flow</a> has changed in three ways that matter:</p><ul><li><strong>Flow’s syntax has converged with TypeScript’s:</strong> if you know TypeScript, you already know most of Flow.</li><li><strong>Flow has features TypeScript lacks:</strong> match expressions and first-class component/hook/renders.</li><li><strong>Where the two diverge, Flow keeps the safer default:</strong> catching patterns TypeScript accepts that can throw at runtime, silently corrupt values, or cause logic bugs.</li></ul><h3>Flow and TypeScript syntax have converged</h3><p>Is it Flow or TypeScript? You can’t tell:</p><pre>type User = {<br>  readonly name: string,<br>  readonly age: number,<br>  readonly metadata: unknown,<br>};<br><br>function get&lt;K extends keyof User&gt;(user: User, key: K): User[K] {<br>  return user[key];<br>}<br><br>declare const user: User;<br>const age: number = get(user, &#39;age&#39;);</pre><p>If you know TypeScript, this all looks familiar. The example above uses keyof, readonly props, unknown, indexed access (T[K]), and extends bounds - and there&#39;s also conditional types, mapped types, type guards, and as const.</p><p>The rest of this post is where Flow goes beyond TypeScript.</p><h3>Flow-only features</h3><p>Flow has features TypeScript lacks:</p><h3>match expressions and statements</h3><p>Flow has match: pattern matching as an expression. It&#39;s exhaustively checked, with structural patterns that destructure as they match. Forget a case, like type: &#39;remove&#39;, and match flags it and tells you what to add.</p><pre>type Action = <br>  | {type: &#39;add&#39;, text: string}<br>  | {type: &#39;toggle&#39;, id: string}<br>  | {type: &#39;remove&#39;, id: string};<br><br>declare const action: Action;<br><br>const description = match (action) { // ERROR: &#39;remove&#39; case missing<br>  {type: &#39;add&#39;, const text} =&gt; `Add: ${text}`,<br>  {type: &#39;toggle&#39;, const id} =&gt; `Toggle ${id}`,<br>};</pre><p>match also has a statement form: a safer switch with no fall-through and all the features of match expressions.</p><h3>React: component, hook, renders</h3><ul><li><strong>component syntax:</strong> React components as a first-class language construct. Direct prop declaration as named parameters, and React-specific correctness the type-checker can enforce.</li><li><strong>renders types: </strong>declare composition contracts for components. Design systems and libraries can specify what slots accept and what components produce, with the type checker enforcing the contracts across wrapper components.</li><li><strong>hook syntax: </strong>declares hooks as a first-class kind, distinct from regular functions. Flow enforces the <a href="https://react.dev/reference/rules">Rules of React</a> in the type checker: catching conditional calls, hook/function conflation, and unsafe mutations of hook return values during render, without a separate ESLint plugin.</li></ul><pre>component Header(text: string, color: string) {<br>  return &lt;div style={{color}}&gt;{text}&lt;/div&gt;;<br>}<br>component MainHeader(text: string) renders Header {<br>  return &lt;Header text={text} color=&quot;red&quot; /&gt;;<br>}<br><br>component Layout(header: renders Header) {<br>  return &lt;div&gt;<br>    {header}<br>    &lt;section&gt;Content&lt;/section&gt;<br>  &lt;/div&gt;;<br>}<br><br>const ok = &lt;Layout header={&lt;MainHeader text=&quot;Flow&quot; /&gt;} /&gt;;<br>const bad = &lt;Layout header={&lt;footer /&gt;} /&gt;; // ERROR</pre><h3>Four runtime crashes TypeScript doesn’t catch — but Flow does</h3><p>This is where the two still part ways. Each example below type-checks in TypeScript 6.0.3 with strict enabled - then crashes at runtime.</p><ol><li><strong>Extracting a method from an instance loses its </strong><strong>this binding in TypeScript</strong></li></ol><pre>class Counter {<br>  count: number = 0;<br>  increment(): number {<br>    return ++this.count;<br>  }<br>}<br>const counter = new Counter();<br>const tick = counter.increment;  // TS accepts. Flow rejects.<br>tick();  // Runtime crash! `this` is undefined inside `increment`</pre><p>Pulling counter.increment off the instance detaches the method from counter, so the later tick() runs with this undefined and ++this.count throws. TypeScript types the extracted method as a plain function and waves the call through. Flow rejects the unbound method extraction at the point where this is lost.</p><p><strong>2. TypeScript lets extra properties slip through indirect assignment</strong></p><pre>type Prices = {apple: number, banana: number};<br>const items = {apple: 1.5, banana: 0.5, sample: &quot;free&quot;};<br>const prices: Prices = items;  // TS accepts. Flow rejects.<br>Object.values(prices).map(<br>  price =&gt; price.toFixed(2), // Runtime crash! `sample` isn&#39;t a number<br>);</pre><p>TypeScript’ object types allow extra properties at the type level — the “excess property check” that could catch {apple: 1.5, sample: &quot;free&quot;} only fires on <em>direct</em> object literal assignment. Indirect paths (like assigning through a variable) lose that check, and the extra sample property slips through. Flow&#39;s object types are exact by default: extra properties are always rejected.</p><p><strong>3. TypeScript lets you push a wider value into a narrower mutable array</strong></p><pre>// TypeScript: accepted.<br>function appendError(errs: Array&lt;string | Error&gt;) {<br>  errs.push(new Error(&quot;oops&quot;));<br>}<br>const errors: Array&lt;string&gt; = [];<br>appendError(errors);  // TS accepts. Flow rejects.<br>errors[0].toUpperCase();  // Runtime crash! `errors[0]` isn&#39;t a string</pre><p>TypeScript treats Array&lt;string&gt; as a subtype of Array&lt;string | Error&gt; (mutable arrays are covariant in TS), so the call goes through and the push inside appendError adds an Error in the caller&#39;s string-typed array. Flow&#39;s mutable-array invariance blocks the widening at the call site. If the function doesn&#39;t actually need to mutate, the fix is ReadonlyArray&lt;string | Error&gt;: removing the possibility of mutation makes the widening safe.</p><p><strong>4. Type-guard bodies aren’t validated in TypeScript</strong></p><pre>// TypeScript: accepted, but this body is true for numbers, not strings.<br>function isString(x: unknown): x is string {<br>  return typeof x === &quot;number&quot;;  // TS accepts. Flow rejects.<br>}<br>const data: unknown = 1;<br>if (isString(data)) {<br>  data.toUpperCase();  // Runtime crash! `data` isn&#39;t a string<br>}</pre><p>TypeScript checks the <em>signature</em> of a predicate, not the body. Flow validates the body in both directions: every return must actually refine to the guard type, and the negation must refine the guard type away. It rejects predicates that lie about what they check.</p><h3>Read the full comparison</h3><p>The full doc, <a href="https://flow.org/en/docs/flow-vs-typescript/"><strong>Flow for TypeScript Users in 2026</strong></a>, has 20+ side-by-side Flow vs. TypeScript comparisons.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ad07ac0a2d92" width="1" height="1" alt=""><hr><p><a href="https://medium.com/flow-type/flow-for-typescript-users-in-2026-ad07ac0a2d92">Flow for TypeScript Users in 2026</a> was originally published in <a href="https://medium.com/flow-type">Flow</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Flow Natural Inference for Primitives]]></title>
            <link>https://medium.com/flow-type/flow-natural-inference-for-primitives-df27149109bb?source=rss----ab067ae921ed---4</link>
            <guid isPermaLink="false">https://medium.com/p/df27149109bb</guid>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[flow]]></category>
            <category><![CDATA[type-systems]]></category>
            <dc:creator><![CDATA[Panagiotis Vekris]]></dc:creator>
            <pubDate>Fri, 30 May 2025 05:06:19 GMT</pubDate>
            <atom:updated>2025-05-30T05:07:07.523Z</atom:updated>
            <content:encoded><![CDATA[<h3>Natural Inference for Primitives in Flow</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*sbfNsbgaALNZpsKYwM-cRA.jpeg" /><figcaption>Photo from <a href="https://www.pexels.com/@mali/">mali maeder</a> from <a href="https://www.pexels.com/photo/pathway-between-green-leafed-trees-109391/">pexels</a></figcaption></figure><p><em>🌿 We are announcing Natural Inference for Flow, an improved way to infer types for primitive values, that resolves a long-standing correctness gap and source of confusion.</em></p><p>🌟 <em>We are also introducing </em><a href="https://flow.org/en/docs/types/const-expression/"><em>const-expressions</em></a><em> and </em><a href="https://flow.org/en/docs/types/const-expression/#const-type-parameters"><em>const-type parameters</em></a><em>, two new features that can help address Flow errors related to this change.</em></p><h3>What was the problem before?</h3><p>Prior to Natural Inference, you could write the following code without Flow complaining</p><pre>const shape = {<br>  type: &#39;circle&#39;,<br>  radius: 42,<br>};<br><br>if (condition) {<br>  shape.type = &#39;square&#39;; // ⚠️ this was allowed<br>};<br>shape.type as &#39;circle&#39;; // no error here ☹️<br>//    ^<br>//    hover type returns `string`</pre><p>In other words, Flow allowed both</p><ul><li>the assignment of &#39;square&#39; to shape.type, and</li><li>the <em>unsafe</em> assertion that shape.type is still &#39;circle&#39; in the end.</li></ul><p>To add insult to injury, when hovering over shape.type Flow would show string, which was a lie, since a string-typed expression is not compatible with the type &#39;circle&#39;.</p><h3>How does Natural Inference fix this?</h3><p>In code like the above, Flow will now truly infer the type {type: string, radius: number} for shape. This means that</p><ul><li>assigning shape.type = &#39;square&#39; is still allowed, but</li><li>asserting shape.type as &#39;circle&#39; will now be an error.</li></ul><p>This change comes at the cost of Flow potentially erroring in code that rightfully did not error before. For example, if we remove the update in the code above</p><pre>const shape = {<br>  type: &#39;circle&#39;,<br>  radius: 42,<br>};<br><br>shape.type as &#39;circle&#39;;</pre><p>Flow will still error because shape.type is truly inferred as a string. We will later see how to address this kind of errors.</p><h3>How does Natural Inference work?</h3><p>At the core of the outgoing problematic behavior was the internal type representation for string, number and boolean literal values. These types were a hybrid between the general <a href="https://flow.org/en/docs/types/primitives/">primitive types</a> (string, number, boolean), and the respective <a href="https://flow.org/en/docs/types/literals/">literal values as types</a> (abc, 42, etc.). Flow would opportunistically pick either version of these type at each <em>use-site</em>, without ensuring they were used consistently.</p><p>Natural Inference fixes this by deciding on one of the two versions at the point where the literal is <em>introduced</em> (get assigned to a variable, gets passed to a function, etc.). This type is then used consistently for the rest of the program.</p><p>This decision mainly relies on the presence of type annotations around the literal. Some key rules are the following:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*PBnmll3I8HZgH-eAyaB2Fw.png" /></figure><p>To see the rationale behind the last rule consider calls to <a href="https://github.com/facebook/flow/blob/bd30b8bd7322ecf7707b2c469bd4faef7cd194f6/lib/react.js#L788-L797">React.useState</a>:</p><pre>const [state, setState] = React.useState(&#39;a&#39;);<br>setState(&#39;b&#39;);</pre><p>Calls to setState will only be meaningful if they accept state as string, instead of the very restrictive &#39;a&#39;.</p><h3>Migration</h3><p>Natural inference is available as of version 0.271.0 by adding the following line in the [options] section of the .flowconfig:</p><pre>experimental.natural_inference.local_primitive_literals=full</pre><p>In version 0.273.0 and forward it will be enabled by default.</p><h3>How to fix errors caused by Natural Inference</h3><p>Most new errors can be resolved by adding some annotation to guide inference around primitive values. Consider the following example:</p><pre>type Shape = {<br>  type: &#39;circle&#39;,<br>  radius: number,<br>} | {<br>  type: &#39;square&#39;,<br>  side: number,<br>};<br><br>function takesShape(shape: Shape): void { ... };</pre><p>The following call will now be an error</p><pre>const circle = {<br>  type: &#39;circle&#39;,<br>  radius: 42,<br>};<br><br>takesShape(circle); // error: string (inferred type for &quot;circle&quot; value)<br>                    // is incompatible with both &#39;circle&#39; and &#39;square&#39; types</pre><h4>A. Fix with const-expressions <a href="https://flow.org/en/docs/types/const-expression/">[docs]</a> 🌟</h4><p>Use &#39;circle&#39; as const to declare that you want &#39;circle&#39; to be inferred as the <a href="https://flow.org/en/docs/types/literals/">singleton type</a> &#39;circle&#39;. This will allow circle to be inferred as the part of Shape that corresponds to a circle:</p><pre>const circle = {<br>  type: &quot;circle&quot; as const,<br>  radius: 42,<br>}; // circle inferred as {type: &#39;circle&#39;, radius: number}<br><br>takesShape(circle); // okay</pre><p>Note that as const can be used to annotate containers too (objects and arrays). Its effect is applied to the parts of the container.</p><p>For example, definitions that before looked like this</p><pre>const ACTION = {<br>  SELL: &#39;SELL&#39;,<br>  BUY: &#39;BUY&#39;,<br>};<br><br>type ActionType = $Values&lt;typeof ACTION&gt;;</pre><p>will now work as expected, ie. ActionType will be &#39;SELL&#39;|&#39;BUY&#39;, if ACTION is defined as</p><pre>const ACTION = {<br>  SELL: &#39;SELL&#39;,<br>  BUY: &#39;BUY&#39;,<br>} as const;</pre><p>Otherwise ActionType will just be string.</p><h4>B. Fix using a type annotation</h4><p>When an annotation like Shape is available, you can also use it to initialize circle:</p><pre>const circle: Shape = {<br>  type: &#39;circle&#39;,<br>  radius: 42,<br>};<br><br>takesShape(circle); // okay</pre><p>Note that Flow will infer &#39;circle&#39; with its precise type so that the check of the initializer object against the annotation Shape succeeds.</p><h4>C. Fix with Const-Type Parameters <a href="https://flow.org/en/docs/types/const-expression/#const-type-parameters">[Docs]</a> 🌟</h4><p>In some cases, it is useful to specify that an argument to a function is always expected to be a const-expression. You can do so by annotating the type parameter with the const modifier. For example, in</p><pre>declare function takesConst&lt;const X&gt;(x: X): [X];<br>const x = takesConst({prop: 42});</pre><p>Variable x will be inferred as [{+prop: 42}], instead of [{prop: number}] that we would otherwise get.</p><h4>D. Annotate the Container</h4><p>When adding elements, say strings, to a container, e.g. an array, then Flow will now infer a type based on the general form of the elements being added. Consider, for example</p><pre>function foo(): $ReadOnlyArray&lt;&#39;a&#39;|&#39;b&#39;&gt; {<br>  const arr = [];<br>  arr.push(&#39;a&#39;);<br>  arr.push(&#39;b&#39;);<br>  return arr;<br>}</pre><p>Flow used to not complain about this code, but did so in a problematic way, since the following signature was also allowed:</p><pre>function foo(): $ReadOnlyArray&lt;&#39;a&#39;&gt; { ... }</pre><p>Now, Flow will error in the above code, since it will truly infer the type Array&lt;string&gt; for arr. To fix this example, all you need to do is add an annotation to arr to indicate the target type of the array:</p><pre>function foo(): $ReadOnlyArray&lt;&#39;a&#39;|&#39;b&#39;&gt; {<br>  const arr: Array&lt;&#39;a&#39;|&#39;b&#39;&gt; = [];<br>  arr.push(&#39;a&#39;);<br>  arr.push(&#39;b&#39;);<br>  return arr;<br>}</pre><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=df27149109bb" width="1" height="1" alt=""><hr><p><a href="https://medium.com/flow-type/flow-natural-inference-for-primitives-df27149109bb">Flow Natural Inference for Primitives</a> was originally published in <a href="https://medium.com/flow-type">Flow</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Announcing: Mapped Types + Pick, Omit, and Record]]></title>
            <link>https://medium.com/flow-type/announcing-mapped-types-pick-omit-and-record-75b883c80749?source=rss----ab067ae921ed---4</link>
            <guid isPermaLink="false">https://medium.com/p/75b883c80749</guid>
            <category><![CDATA[flow]]></category>
            <category><![CDATA[javascrıpt]]></category>
            <dc:creator><![CDATA[Jordan Brown]]></dc:creator>
            <pubDate>Tue, 06 Aug 2024 21:23:59 GMT</pubDate>
            <atom:updated>2024-08-06T21:24:52.004Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2owqK37DhgF6nh6rgWvS1A.jpeg" /><figcaption>Photo by Mihis Alex on pexels.com</figcaption></figure><p><em>tl;dr: Mapped types allow you to transform object types into other object types. We have added definitions for </em><em>Pick, </em><em>Omit, and </em><em>Record utility types to our library definitions. </em><a href="https://flow.org/en/docs/types/mapped-types/"><em>Docs here</em></a><em>.</em></p><p>Mapped Types are enabled by default as of <a href="https://github.com/facebook/flow/blob/main/Changelog.md#02120">Flow v0.212</a>. To use them, make sure you are following our recommended setup in <a href="https://flow.org/en/docs/install/#setup-compiler">our docs</a>. Mapped Types (<a href="https://www.typescriptlang.org/docs/handbook/2/mapped-types.html">inspired by TypeScript</a>) provide an elegant syntax for transforming object types:</p><pre>type Obj = {<br>  foo: number,<br>  bar: string,<br>  baz: boolean,<br>};<br><br>type Accessor&lt;+T&gt; = () =&gt; T;<br><br>type ObjWithAccessors = {[key in keyof Obj]: Accessor&lt;Obj[key]&gt;};<br><br>function f(o: ObjWithAccessors): number {<br>  return o.foo();<br>}</pre><p>In this example, ObjWithAccessors is a Mapped Type that turns each property of Obj into a function returning the type defined in Obj. It does this all without requiring you to list out the property names again, and changes to the definition of Obj will be reflected in ObjWithAccessors.</p><p>We’ve also implemented the highly requested utility types Pick, Omit, and Record using Mapped Types and <a href="https://medium.com/flow-type/announcing-conditional-types-765b421f3a87">Conditional Types</a>. We’ve added them to our <a href="https://github.com/facebook/flow/blob/28e31fbde379a63240b6902d6d0965570b362a36/lib/core.js#L2811-L2827">library definitions</a>.</p><p>Mapped Types bring several improvements over <a href="https://flow.org/en/docs/types/utilities/#toc-objmap">$ObjMap</a>, our previous solution for mapping object types:</p><ol><li>The syntax is cleaner and easier to both read and write</li><li>The expressive power is increased, allowing you to add optionality and variance modifiers in addition to the value type transformation</li><li>The underlying representation is crisp and principled, which creates a more reliable and consistent experience</li></ol><p>You can find documentation for the feature on <a href="https://flow.org/en/docs/types/mapped-types/">our website</a>.</p><h3>Basic Usage</h3><p>Mapped Types have syntax similar to indexed object types but use the in keyword:</p><pre>type O = {foo: number, bar: string};<br>type Boxify&lt;T&gt; = {contents: T};<br>type MappedType = {[key in keyof O]: Boxify&lt;O[key]&gt;};</pre><p>Combined with the keyof keyword, MappedType has all of the keys from O with all of the value types transformed by Boxify&lt;O[key]&gt;. The key variable is substituted for each key in O when creating the property, so this type evaluates to:</p><pre>{<br>foo: Boxify&lt;O[&#39;foo&#39;]&gt;,<br>bar: Boxify&lt;O[&#39;bar&#39;]&gt;,<br>}<br>= {<br>foo: {contents: number},<br>bar: {contents: string},<br>}</pre><p>In addition to transforming the value types, you can also add optionality and <a href="https://flow.org/en/docs/lang/variance/">variance</a> modifiers:</p><pre>type ReadOnlyOptionalBoxes = {+[key in keyof O]?: Boxify&lt;O[key]&gt;};<br>// = {+foo?: {contents: number}, +bar?: {contents: string}</pre><h3>Generating Objects from Keys</h3><p>You can also use mapped types to turn a string literal union into an object type by using in with a union of valid key types (no keyof needed!)</p><pre>type Union = &#39;mapped&#39; | &#39;types&#39; | &#39;rock&#39;;<br>type Obj = {[key in Union]: number};<br>// = {mapped: number, types: number, rock: number}</pre><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=75b883c80749" width="1" height="1" alt=""><hr><p><a href="https://medium.com/flow-type/announcing-mapped-types-pick-omit-and-record-75b883c80749">Announcing: Mapped Types + Pick, Omit, and Record</a> was originally published in <a href="https://medium.com/flow-type">Flow</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[New Flow Language Features for React]]></title>
            <link>https://medium.com/flow-type/announcing-component-syntax-b6c5285660d0?source=rss----ab067ae921ed---4</link>
            <guid isPermaLink="false">https://medium.com/p/b6c5285660d0</guid>
            <category><![CDATA[reactjs]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[react]]></category>
            <category><![CDATA[react-native]]></category>
            <dc:creator><![CDATA[Alex Taylor]]></dc:creator>
            <pubDate>Wed, 03 Apr 2024 19:30:24 GMT</pubDate>
            <atom:updated>2024-04-09T17:17:18.573Z</atom:updated>
            <content:encoded><![CDATA[<h4><em>Write Safer and more Succinct React with Flow</em></h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/932/1*ofDWSeYHJ0mOxhOqA-XhgA.png" /></figure><p>We have thousands of engineers committing React code every day to Meta’s largest codebases. Part of our responsibility on the Flow team is to make it as easy as possible for <em>anyone</em> to contribute, from design system React experts to C++ engineers making one-off internal pages to support their backend services. Over the last year, we’ve built several new language features to make it easier than ever to write high-quality React code, and we’ve built powerful new tools for design system owners to express their design constraints in the type system itself.</p><p>Flow is excited to announce<a href="https://flow.org/en/docs/react/component-syntax/"> Component Syntax</a>, adding first-class support for React primitives such as components and hooks to the Flow language. These features bring improved ergonomics, expressiveness, and static enforcement for many of the <a href="https://react.dev/reference/rules">Rules of React</a>.</p><p>We’ve already adopted Component Syntax across all our codebases at Meta, and the results have been incredible: we’ve seen a massive reduction in boilerplate for writing components, we’ve caught thousands of violations of the <a href="https://react.dev/reference/rules">Rules of React</a>, and we’ve seen design systems codify their stylistic rules in the type system. Most importantly, our engineers love the new features. We’re excited to share these features with the broader community.</p><p>If you’re already using React in your own Flow projects, you can enable these new features by upgrading to Flow <a href="https://github.com/facebook/flow/releases/tag/v0.233.0">v0.233.0</a> or later.</p><p><strong>None of this is required to use React</strong>, but if you’re already using Flow these features may be interesting to you.</p><h4>Component Syntax Features</h4><p>Component Syntax introduces several new features:</p><ul><li><strong>New Component declaration.</strong> Dedicated syntax for defining components that is ergonomic to use, reduces boilerplate code, and provides greater safety by enforcing many of the <a href="https://react.dev/reference/rules">Rules of React</a>.</li><li><strong>New Hook declaration.</strong> Dedicated syntax for defining hooks that provides additional safety by enforcing the <a href="https://react.dev/reference/rules/rules-of-hooks">rules of hooks</a>.</li><li><strong>Statically enforced Design System rules with render types.</strong> We’ve introduced<a href="https://flow.org/en/docs/react/render-types/"> render types</a>, a powerful tool for design systems that makes it simple to express stylistic constraints through types.</li></ul><h4><em>A Tour of Component Syntax</em></h4><p><strong>Code today 😴</strong></p><pre>type Props = $ReadOnly&lt;{<br>  text?: string,<br>  onClick: () =&gt; void,<br>}&gt;;<br><br>export default function HelloWorld({<br>  text = &#39;Hello!&#39;,<br>  onClick,<br>}: Props): React.MixedElement {<br>  return &lt;div onClick={onClick}&gt;{text}&lt;/div&gt;;<br>}</pre><p><strong>Component Syntax 🔥</strong></p><pre>export default component HelloWorld(<br>  text: string = &#39;Hello!&#39;,<br>  onClick: () =&gt; void,<br>) {<br>  return &lt;div onClick={onClick}&gt;{text}&lt;/div&gt;;<br>}</pre><h3>The Basics</h3><p>As you can see, components are quite similar to functions, but with a few differences:</p><ul><li>Replace the function keyword with component.</li><li>Use individual params instead of a props object, specifying default values inline is supported.<br>– This removes the duplication required when using object destructuring and removes the need for modifiers like $ReadOnly&lt;{…}&gt;.</li><li>No return type is needed unless using<a href="https://flow.org/en/docs/react/render-types/"> render types</a>. Flow enforces the returned value will always be a subtype of React.Node.</li></ul><h3>Full compatibility</h3><p>Components are designed to fully replace their functional counterparts. To achieve this, we’ve added a few more features to support all prop types, include rest parameters, and props that use invalid JavaScript identifiers, as with html data attributes (data-&lt;attr&gt;).</p><pre>export default component HelloWorld(<br>  &#39;data-testid&#39; as testid: string, // [1]<br>  ...otherProps: OtherProps // [2]<br>) {<br>  return &lt;div data-testid={testid} {...otherProps} /&gt;&lt;/div&gt;;<br>}</pre><ol><li>String props are allowed but must be renamed via as.</li><li>Creating props objects via rest params is also supported.</li></ol><h3>Improved Safety</h3><p>Beyond the obvious syntactic advantages, Component Syntax also introduces new capabilities that allow Flow to better understand your code and enforce React best practices to help avoid common pitfalls. In the next sections we’ll cover a few of these features.</p><h3>Ensuring props are deep read-only</h3><p>One of the basic rules of React is that<a href="https://react.dev/learn/keeping-components-pure"> a component’s props shouldn’t be mutated</a>. Historically, this behavior has been partially enforced by the common practice of wrapping prop types with $ReadOnly&lt;&gt;. With Component Syntax, all props are checked to ensure they are not mutated during render. This means that you won’t need to add $ReadOnly&lt;&gt; anymore (including on rest props), and you’ll get additional Flow coverage to ensure that properties are <a href="https://flow.org/try/#1N4Igxg9gdgZglgcxALlAIwIZoKYBsD6uEEAztvhgE6UYCe+JADpdhgCYowa5kA0I2KAFcAtiRQAXSkOz9sADwxgJ+NPTbYuQ3BMnTZA+Y2yU4IwRO4A6SFBIrGVDGM7c+IFkolXpUCWewUEAwhCQgRDH8wEH4hMnwROHlsNnw4KHwwSLAAC3wANyo4LFxscWQuHgMNZmwsiRSAWglaY1cq-hIAa2wJXNpG4Vxcdvdu3v7B0RxKUYMhKDBSqmbWwIq3eagoOrKSKgH0wtMMPznY7d2SfcoBiEZ-aG5G3Ix085AF-ZhsRoRehqUEiNMgSQHlSruBZxJrMcJwMhzAC+-EgGiCZkYEEoEgABMAYQBlSwNXi4mEAURgP2USNxMEo4VxAHJPMpmQBuAA6UB5kBEWJ2flxADFiAAKCBoABWyHxVEocoAgtQ6AAeYQiGYAPiRAEp8TzcbjbPZcTsAO4AeRluIAvPirE6pdKkdyoMaAPSe3EUgBKfqtfoAhLiAJoQIQm+5wFK4iQ5bC4yOA5Myup4tCheOJ3HpHaUXEKuh5ki4+xwYa4kShSIpI3m7DWmVWBUAbQADABde24gDMHNxPIbLAkQkoHqGuHdSJiIHyJhIcGgQXyHasACY+32rB2QEigA">deeply protected</a> from writes as well.</p><pre>type Item = { <br>  itemName: string,<br>  arr: Array&lt;number&gt;,<br>};<br>type OtherProps = {<br>  userId: number,<br>};<br><br>component UserItem(userItem: Item, ...props: OtherProps) {<br>  props.userId = 0; // Error: react-rule-unsafe-mutation<br>  userItem.itemName = &quot;Cool New Laptop&quot;;  // Error: react-rule-unsafe-mutation<br><br>  const copiedObj = {...userItem};<br>  copiedObj.arr[0] = 3; // Error: Deep checking catches error through copied object<br>}</pre><p>The last error above was particularly exciting for us to catch! We’ve seen many cases where the programmer clearly understood the Rules of React and would copy objects instead of mutating them directly, but they would still erroneously mutate values that were only aliased, not copied. Immutability can be subtle even for experienced developers.</p><p>This feature helps prevent a common class of bugs while removing the need for boilerplate that was previously universal. This feature does have its limits, though. At present Flow is only able to detect mutations of props in a component or hook, and we optimistically assume that method calls do not cause mutations.</p><h3>Enforcing best practices with Refs</h3><p>Another pattern we enforce in component bodies is that refs are not read or written to during render. This is another common pitfall that can lead to unintended behavior. Check out the <a href="https://react.dev/reference/react/useRef">React documentation</a> for more information. Here is an example of this in action:</p><pre>component MyComponent() {<br>  const renderCount = useRef&lt;number&gt;(0);<br>  renderCount.current += 1; // error<br>  return &lt;div&gt;{renderCount.current}&lt;/div&gt; // error<br>}</pre><p>In order to safely use refs in your components, you can read or write to refs from event handlers or effects instead:</p><pre>component MyComponent() {<br>  const renderCount = useRef&lt;number&gt;(0);<br>  const [count, setCount] = useState(0);<br>  useEffect(() =&gt; {<br>    renderCount.current += 1; // ok<br>    setCount(renderCount.current); // ok<br>  }, [renderCount]);<br>  return &lt;div&gt;{count}&lt;/div&gt;<br>}</pre><p>In total, these features make it easier for programmers and reviewers to focus on the business logic instead of writing bug-free code. Let Flow sort out the details– you can focus on impact.</p><h3>Hook Syntax</h3><p>Hooks are another fundamental abstraction in React that can benefit from improved type checking validation. We’ve introduced the hook keyword that can be used in place of function when declaring custom hooks. This allows flow to enforce that hooks adhere to the React programming model:</p><ul><li>Hooks must be called in the same order on every render (which implies that hooks may not be called conditionally).</li><li>Hooks must operate under the same restrictions as component bodies, such as not reading ref.current or mutating any passed in parameters.</li><li>When called, hooks must obey the useFoonaming convention. For example, use_foo() or myHook() would lead to a flow error.</li><li>As the converse of the above, non-hook functions used within components or other hooks should not have names that match the useFoo pattern.</li></ul><p>Many of these rules are already enforced by <a href="https://www.npmjs.com/package/eslint-plugin-react-hooks">React’s ESLint plugin</a>, but we also apply the validations discussed in the components section to hooks.</p><p>As you can see from the examples below, the only change necessary to adopt hook syntax is to replace function with hook.</p><p><strong>Code Today 😴</strong></p><pre>function useOnlineStatus(initial: boolean): boolean {<br>  const [isOnline, setIsOnline] = useState(initial);<br>  useEffect(() =&gt; {<br>    // ...<br>  }, []);<br>  return isOnline;<br>}</pre><p><strong>Hook Syntax 🔥</strong></p><pre>hook useOnlineStatus(initial: boolean): boolean {<br>  const [isOnline, setIsOnline] = useState(initial);<br>  useEffect(() =&gt; {<br>    // ...<br>  }, []);<br>  return isOnline;<br>}</pre><p>Check out the <a href="https://flow.org/en/docs/react/hook-syntax/">hooks documentation</a> for more information.</p><h3>Render Types</h3><p>Render types are a powerful new feature providing an ergonomic way to define how components should be composed. We designed render types to make working with component libraries safer and easier. At its core, render types consist of a new renders type annotation that can be used to specify what a component ultimately renders. Here is an example:</p><pre>// Component library<br>export component Header() { ... }<br><br>export component Layout(<br>  header: renders Header,  // Library components can specify what props should render<br>) { ... }<br><br><br>// Product code<br>component MyHeader() renders Header { // Components can describe what they will ultimately render<br>  // ...<br>  return &lt;Header /&gt;;<br>}<br><br>export component MyLayout() {<br>  // OK! MyHeader renders Header<br>  return &lt;Layout header={&lt;MyHeader /&gt;} /&gt;; <br>}</pre><p>Remember, not everyone at Meta who needs to write React code is a front-end expert. Design systems make it easy for people with relatively little experience to make beautiful cohesive UIs. Render types let the design system owners codify their design rules in the type system, which helps all the downstream users build even more delightful experiences without having to know much about UX or UI design.</p><p>With render types, you can also:</p><ul><li>Describe optional rendering, or rendering a list of items with the renders? and renders* <a href="https://flow.org/en/docs/react/render-types/#rendering-optional-elements">variants</a>.</li><li>Use component names as shorthand for easily referring to component types. For example, Header is equivalent to React.Element&lt;typeof Header&gt;.</li></ul><p>Check out the <a href="https://flow.org/en/docs/react/render-types/">render types documentation</a> for a lot more information on render types.</p><h3>Try it out</h3><p>To see Component Syntax in action or try it out for yourself, check out our <a href="https://github.com/alexmckenley/react-flow-vite-template">example app on GitHub</a>.</p><h3>Conclusion</h3><p>Component Syntax introduces a novel approach to building React UIs, offering enhanced type safety, readability, and developer efficiency. It reduces boilerplate for components, enforces React best practices, and allows developers to safely express common design-system patterns.</p><p>We designed component Syntax in coordination with the React team, and are already using it across our codebases at Meta. We plan to continue expanding Flow’s understanding of React in the future and improve safety and expressivity when working with React.</p><p>—</p><p><em>Written by Alex Taylor and Jordan Brown</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b6c5285660d0" width="1" height="1" alt=""><hr><p><a href="https://medium.com/flow-type/announcing-component-syntax-b6c5285660d0">New Flow Language Features for React</a> was originally published in <a href="https://medium.com/flow-type">Flow</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Announcing User Defined Type Guards in Flow]]></title>
            <link>https://medium.com/flow-type/announcing-user-defined-type-guards-in-flow-b979bb2e78cf?source=rss----ab067ae921ed---4</link>
            <guid isPermaLink="false">https://medium.com/p/b979bb2e78cf</guid>
            <dc:creator><![CDATA[Panagiotis Vekris]]></dc:creator>
            <pubDate>Tue, 05 Mar 2024 22:27:14 GMT</pubDate>
            <atom:updated>2024-03-07T19:56:53.001Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/706/1*dpF4Tf97ukK5wCUCeDbCbg.png" /></figure><p>Flow now lets you define a function that encodes a type predicate over its parameter. This predicate, which we refer to as a <a href="https://flow.org/en/docs/types/type-guards/"><em>type guard</em></a>, is annotated in place of a return type annotation as x is PredicateType. It declares that if the function returns true then its parameter x is of type PredicateType.<br><br>The syntax for such a function, similar to how it appears in TypeScript, is</p><pre>function predicate(x: InputType): x is PredicateType {<br>  return &lt;some_expression&gt;;<br>}</pre><p>The library definition for Array .filter has also been updated to recognize callbacks with type (x: Input) =&gt; x is PredType and refine arrays of type Array&lt;Input&gt; to Array&lt;PredType&gt;.</p><h3>Background</h3><p>The ability to use Array .filter to produce arrays with refined types has been one of the most commonly requested features in feedback that the team has gathered over the past several years.<br><br>Predicate functions based on the <a href="https://flow.org/en/docs/types/functions/#predicate-functions">%checks</a> annotation are not a good fit for higher order functions, such as Array’s .filter method, and so they do not support this use case. A feature that relies on typing, such as type guards, is a more natural way of <a href="https://github.com/facebook/flow/blob/57a92b842fc032ab2cfc94dd4bb2d9613a7cb2a2/lib/core.js#L743">expressing this refinement</a>.<br><br>At the same time, the refinement based on %checks functions has been known to be hard-to-understand and spotty. Robust support for refining using function predicates is essential for a dynamic language like JavaScript.</p><h3>Basic Usage</h3><p>Let&#39;s see a simple example where we define a type guard function over a data type</p><pre>type A = { type: &quot;A&quot;; data: string };<br>type B = { type: &quot;B&quot;; data: number };<br>type AorB = A | B;<br><br>function isA(value: AorB): value is A {<br>  return value.type === &quot;A&quot;;<br>}</pre><p>Function isA will return true if (and only if) its input value has type A. It can therefore be used to refine values of type AorB down to A:</p><pre>function test(x: AorB) {<br>  if (isA(x)) {<br>    // `x` has now been refined to type A.<br>    // We can assign to it variables of type A ...<br>    const y: A = x;<br>    // ...and access A&#39;s properties through `x`<br>    const stringData: string = x.data;<br><br>    // As a sanity check, the following assignment to B will error<br>    const error: B = x;<br>  }<br>}</pre><h3>Array .filter</h3><p>Flow now recognizes when you call filter on an array of type Array&lt;T&gt;, with a callback function with type (value: T) =&gt; value is S. It returns an array of type Array&lt;S&gt;. Note that S needs to be a subtype of the type of the array element T.<br><br>Here are some examples</p><pre>const isNonMaybe = &lt;A&gt;(x: ?A): x is A =&gt; x != null;  <br><br>function filterNull(response: Array&lt;?number&gt;): Array&lt;number&gt; {<br>  return response.filter(isNonMaybe); // no error<br>}<br><br>// Using the definitions from above<br><br>function filterAs(response: Array&lt;AorB&gt;): Array&lt;A&gt; {<br>  return response.filter(isA); // no error<br>}</pre><p>With proper filtering support, it is now possible to move away from the error-prone pattern of using arr.filter(Boolean) to filter out non-null values from array arr. Instead, a more correct arr.filter(isNonMaybe) can be used. The difference here is that Boolean will also remove from the array all <a href="https://developer.mozilla.org/en-US/docs/Glossary/Falsy">falsy values</a> (including for example 0, &quot;&quot;, false), instead of just null and undefined.</p><h3>Defining Type Guard Functions</h3><p>Flow runs a number of checks to ensure that type guard functions respect their declared predicate. Most of them are unsurprising and you can find details about them in <a href="https://flow.org/en/docs/types/type-guards#toc-restrictions-of-type-guard-functions">the docs</a>.<br><br>The most interesting check is that of consistency of the declared predicate type with the check happening in the body of the function. Specifically Flow establishes two things:</p><ol><li>The type of the refined parameter <em>after</em> the predicate of the return expression has been applied is a subtype of the guard type.</li><li>The refined parameter is not reassigned in the function body.</li></ol><p>The following examples will be errors:</p><pre>function numOrStrError(x: mixed): x is number | string {<br>  return (typeof x === &quot;number&quot;<br>       || typeof x === &quot;boolean&quot;); // error boolean ~&gt; string<br>}<br><br>function isNumberError1(x: mixed): x is number {<br>  x = 1;<br>  return typeof x === &quot;number&quot;; // error x is written to<br>}<br><br>function isNumberError2(x: mixed): x is number { // error x is reassigned<br>  function foo() {<br>    x = 1;<br>  }<br>  foo();<br>  return typeof x === &quot;number&quot;;<br>}</pre><p>Note that TypeScript does <a href="https://www.typescriptlang.org/play#code/GYVwdgxgLglg9mABGEBbA8gJwMpUwUU0zkwAoAPALkXAGsw4B3MASmvMRgGdk0AjAKaZEAH0Rc8MMAHNEAbwBQiRJgFQQmJKSgBPAA4C4wRBwC85xACIUqQZkuixug0ZOJzpq3zhwANgIBDMEsWAG4FAF8FBVBIWAROLgA5fiFCYkwARgpqOgZmNjduXlsheSU3T0zw5VV1TURnQ2MzC2tU+1DEAHpu5Q5ixkwYKCgBJCg4SOjY6HgkbhTSgiISACYcmjB6JlZ2RJK7eR6+gZ5VAK4uGGkwAQATCtn4pGAfUhZy5X73RGqKqLKN5wD41FRqDQTfTNSptGx2SzhCJAA">not perform such check</a>.</p><h3>Migration From %checks</h3><p>Developers are encouraged to convert existing instances of %checks to the more robust and feature-rich type guard syntax when possible.</p><p>This should be straightforward in most cases. For example,</p><pre>const isA = (x: mixed): boolean %checks =&gt; x instanceof A;<br>const isNonMaybe = (x: mixed): boolean %checks =&gt; x != null;</pre><p>can respectively be written as</p><pre>const isA = (x: mixed): x is A =&gt; x instanceof A;<br>const isNonMaybe = &lt;A&gt;(x: ?A): x is A =&gt; x != null;</pre><p>A couple cases where a larger refactoring needs to happen:</p><ul><li>%checks-functions that refine multiple input parameters, since type-guard syntax can only refine a single parameter. (<a href="https://flow.org/try/#1N4Igxg9gdgZglgcxALlAJwKYEMwBcD6aArlLnALYYrgA2WAzvXGCADQgYAeOBARgJ74AJhhhYiNXClzEM7DFCLl602e0hQhcMtCw18ufgAcqyMTXpyQ5LEZNCDx0+cvzOJtBQW49AOkMm+AhEWGhCKsgyRBgAvuoQItQwJHhw0AAEoRgAchC42RI0ABScyOnkcJwYQqzp-GUVVUIAlGW8EBA02FDpAKRgABYYYADW9OnAADo96Zi4RGg9nOkAhAC86Yo0NOkAZLt1qxtbNADc0zHT0yJgdJjpAG6h6aXpAPz0MnBQCOeaw3cMI9nvV3p9PD8-tM4DAillcvlCiVavxms0JtN0lj0iUyuDvghmn9sTjQfifkSLmwQA8MGgmNBqA8AAy+ABMAEZWRyQDEgA">try-Flow</a>)</li><li>Negations of complex predicates, since type-guards need to refer to the entire condition at once. See <a href="https://flow.org/try/#1N4Igxg9gdgZglgcxALlAJwKYEMwBcD6aArlLnALYYrgA2WAzvXGCADQgYAeOBARgJ74AJhhhYiNXClzEM7DFCLl602e0hQhcMtCw18ufgAcqyMTXpyQ5LEZNCDx0+cvzOJtBQW49AOkMm+AhEWGhCKsgyRBgAvuoQItQwJHhw0AAEcPQAyjJwUAgAchI0APJoAOoAFtoY9EY4GAAU9DLI6QD8rZ4FAJTtvBAQNNhQ6QCkYFUYYADW9OnAADpj6Zi4RGhj3ekAvLvpijQ06QA+p+nd-p7kTb17++kA5E8A3CsxKysiYHSY6QA3ULpTjtLp5ArvKBwGDpJoAQiyuR6RRK5WqtXqjSanF692Wqxx7W6+QQvShnygAHoqekAMLQAEYNBkAqZHIQ1HHdE1XB1BpgDDpXAQdJYYVOdLBUJCdLJKCpDJZQ4QXDpIxoHjMPSsFY0sULXDTf7KqCijVasB6CUmYWikT0MCeXhCo1C0QwGZqiCwq55W69XzpPW0iraKoTKYzeasdIZN1xt1odJVLCaWMAMRoEAA7uleJgsPN0kQjMLpurMForXzMmNtAsGiz6CGxZoS5ZDRWoBgEFgdGMfeWhUcaABaKNzO1rUT5IWcackgq+FZsEBMtBMaDUAEABl8ACYAIz7o8gGJAA">this code</a> for example.</li></ul><h3>Adoption</h3><p>See <a href="https://flow.org/en/docs/types/type-guards/#toc-adoption">this section</a> of our docs for what versions of tooling support the new syntax.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b979bb2e78cf" width="1" height="1" alt=""><hr><p><a href="https://medium.com/flow-type/announcing-user-defined-type-guards-in-flow-b979bb2e78cf">Announcing User Defined Type Guards in Flow</a> was originally published in <a href="https://medium.com/flow-type">Flow</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Announcing Conditional Types]]></title>
            <link>https://medium.com/flow-type/announcing-conditional-types-765b421f3a87?source=rss----ab067ae921ed---4</link>
            <guid isPermaLink="false">https://medium.com/p/765b421f3a87</guid>
            <dc:creator><![CDATA[Sam Zhou]]></dc:creator>
            <pubDate>Tue, 05 Mar 2024 21:00:21 GMT</pubDate>
            <atom:updated>2024-03-05T22:53:53.820Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/548/1*kX5EhkWiLPiwmF3SSFTYKw.png" /></figure><p><a href="https://flow.org/en/docs/types/conditional/">Conditional types</a> allow you to choose between two different output types by inspecting an input type. The syntax (inspired by TypeScript) is similar to a ternary expression:</p><pre>type T = CheckType extends ExtendsType ? TrueType : FalseType;</pre><p>If CheckType is a subtype of ExtendsType, the result is TrueType, otherwise it is FalseType.</p><p>We’ve also added new built-in utility types which make use of conditional types, like ReturnType&lt;F&gt;, Parameters&lt;F&gt;, Exclude&lt;T, U&gt;, and Extract&lt;T, U&gt;.</p><h3>Basic Usage</h3><p>The evaluating of the following conditional type is very similar to that of ternary expression:</p><pre>CheckType extends ExtendsType ? TrueType : FalseType</pre><p>You perform a type-level test of whether CheckType is a subtype of ExtendsType. If that’s the case, it will be evaluated to TrueType. Otherwise, it will be evaluated to FalseType.</p><p>As part of the same project, we also support <a href="https://flow.org/en/docs/types/conditional/#toc-infer-type">infer types</a>. Combined with generics, we can finally write down a utility type that reliably extracts the return type of a function:</p><pre>type ReturnType&lt;T: (...args: $ReadOnlyArray&lt;empty&gt;) =&gt; mixed&gt; = <br>  T extends (...args: $ReadOnlyArray&lt;empty&gt;) =&gt; infer Return <br>    ? Return <br>    : any;</pre><h3>New Utility Types</h3><p>Advanced utility types like conditional types are generally not useful for product code, but it is very expressive to let us create utility types <em>in the user land</em>. With conditional types, we can now provide <a href="https://flow.org/en/docs/types/utilities/#toc-return-type">the following types</a> as Flow built-ins, without any special-cased support:</p><ul><li>ReturnType&lt;F&gt;: Obtain the return type of a function type F. e.g. ReturnType&lt;(string, number)=&gt;boolean&gt; = boolean</li><li>Parameters&lt;F&gt;: Obtain the parameters of a function type F in a tuple. e.g. Parameters&lt;(string, number)=&gt;boolean&gt; = [string, number]</li><li>Exclude&lt;T, U&gt;: Exclude from T those types that are assignable to U. e.g. Exclude&lt;1 | 2 | 3 | 4, 1 | 3&gt; = 2 | 4</li><li>Extract&lt;T, U&gt;: Extract from T those types that are assignable to U. e.g. Extract&lt;Car | Dog | Cat, Animal&gt; = Dog | Cat</li><li>ThisParameterType&lt;F&gt;: Extracts the type of the this parameter of a function type F. e.g. ThisParameterType&lt;(this: foo, bar: string) =&gt; void&gt; = foo</li><li>OmitThisParameter&lt;F&gt;: Removes the this parameter from a function type F. e.g. OmitThisParameterType&lt;(this: foo, bar: string) =&gt; void&gt; = (bar: string) =&gt; void</li></ul><p>In addition, the Exclude type is necessary to power another long requested <a href="https://flow.org/en/docs/types/utilities/#toc-omit">Omit</a> type. Combined with mapped types, we hope to help you get rid of most of the confusing <a href="https://flow.org/en/docs/types/utilities/#toc-diff">$Diff</a> and <a href="https://flow.org/en/docs/types/utilities/#toc-rest">$Rest</a>, and <a href="https://flow.org/en/docs/types/utilities/#toc-objmap">$ObjMap</a> type usages.</p><h3>Fixed Array.flat typing</h3><p>Through the <a href="https://flow.org/en/docs/types/conditional/#toc-distributive-conditional-type">distributive property</a> of conditional type, we are finally able to fix the typing of Array.prototype.flat. Now, the following code is correctly inferred to have type Array&lt;number&gt;:</p><pre>[1, [2, 3], 42, [65535]].flat()</pre><h3>Migration</h3><p>The new utility types will be better replacements for most of the existing $Call use cases. In most cases, we found that people are using $Call only for extraction purposes. e.g.</p><pre>type ExtractedPart = $Call&lt;<br>  &lt;T&gt;(($ReadOnlyArray&lt;$ReadOnly&lt;{foo: {bar: T}}&gt;&gt;) =&gt; string) =&gt; T,<br>  SomeBigImportedType,<br>&gt;;</pre><p>can be rewritten as the following with much clearer intention with a combination of <a href="https://flow.org/en/docs/types/indexed-access/">indexed access types</a> and some of the new utility types:</p><pre>type Extracted = Parameters&lt;SomeBigImportedType&gt;[0][number][&#39;foo&#39;][&#39;bar&#39;];</pre><p>Since conditional type is much clearer than $Call, we have deprecated $Call since v0.224.0. You can turn on deprecated-type lint to find all existing uses of $Call and replace them with appropriate types.</p><p>To support the new syntax, you need to update your version of Prettier, hermes-parser Babel plugin, hermes-eslint and more. Check out the <a href="https://flow.org/en/docs/types/conditional/#toc-adoption">adoption section in the docs</a> for more details.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=765b421f3a87" width="1" height="1" alt=""><hr><p><a href="https://medium.com/flow-type/announcing-conditional-types-765b421f3a87">Announcing Conditional Types</a> was originally published in <a href="https://medium.com/flow-type">Flow</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[New type casting syntax for Flow: “as”]]></title>
            <link>https://medium.com/flow-type/new-type-casting-syntax-for-flow-as-3ef41567ff3e?source=rss----ab067ae921ed---4</link>
            <guid isPermaLink="false">https://medium.com/p/3ef41567ff3e</guid>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[flowtype]]></category>
            <dc:creator><![CDATA[George Zahariev]]></dc:creator>
            <pubDate>Tue, 06 Feb 2024 19:35:06 GMT</pubDate>
            <atom:updated>2024-02-27T23:31:07.824Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/344/1*Qz7Vz1kppEptexmWxwn8ww.png" /></figure><p>To make it easier for new users to get started with <a href="https://flow.org/en/docs/">Flow</a>, we’re updating our type casting syntax to use “as”, like TypeScript, Hack, Swift, and others. Say goodbye to the old colon-and-parens syntax:</p><pre>// Before:<br>(1: number);<br>// After:<br>1 as number;</pre><h3>It’s safe, unlike TypeScript</h3><p>Our new type casting syntax behaves just like the old one — no unsafe downcasts allowed, unlike TypeScript’s “as” cast:</p><pre>const fooObj = {foo: 1};<br>// The following errors in Flow, but is allowed in TypeScript!<br>const otherObj = fooObj as {foo: number, bar: string};  // Uh oh<br>const s: string = otherObj.bar; // Oh dear</pre><p>As before, and like TypeScript, “as” performs a type-checking cast, not a runtime one.</p><h3>Adoption</h3><p>To use the new as casting syntax, you need to update your tooling to support the new syntax:</p><ul><li>Flow and Flow Parser: 0.220+</li><li>Prettier: 3.1+</li><li>Babel: use the <a href="https://www.npmjs.com/package/babel-plugin-syntax-hermes-parser">babel-plugin-syntax-hermes-parser</a> plugin version 0.19+, see our <a href="https://flow.org/en/docs/tools/babel/">Babel guide</a> for more details.</li><li>ESLint: use <a href="https://www.npmjs.com/package/hermes-eslint">hermes-eslint</a> plugin version 0.19+, see our <a href="https://flow.org/en/docs/tools/eslint/">ESLint guide</a> for more details.</li></ul><p>Update your codebase:</p><ul><li>Add “casting_syntax=both” to the “[options]” section of your .flowconfig (“both” will become the default value as of Flow version 0.229). This allows you to use both the old colon-cast and the “as” casting syntax.</li><li>To codemod your code, get <a href="https://www.npmjs.com/package/flow-upgrade">flow-upgrade</a> version 2.3.0+, and run “yarn run flow-codemod typeCastToAsExpression”.</li><li>When you have completed codemodding your codebase, you can update the option to “casting_syntax=as” — this will turn using the old casting syntax into an error, with a quickfix to the “as” casting syntax.</li><li>At some point in the future we will remove the option and only support “as” casts, so code update your codebase!</li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=3ef41567ff3e" width="1" height="1" alt=""><hr><p><a href="https://medium.com/flow-type/new-type-casting-syntax-for-flow-as-3ef41567ff3e">New type casting syntax for Flow: “as”</a> was originally published in <a href="https://medium.com/flow-type">Flow</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Improved Flow Docs and Try Flow]]></title>
            <link>https://medium.com/flow-type/improved-flow-docs-and-try-flow-5da5e4831b5e?source=rss----ab067ae921ed---4</link>
            <guid isPermaLink="false">https://medium.com/p/5da5e4831b5e</guid>
            <category><![CDATA[flowtype]]></category>
            <category><![CDATA[flow]]></category>
            <category><![CDATA[javascript]]></category>
            <dc:creator><![CDATA[George Zahariev]]></dc:creator>
            <pubDate>Tue, 19 Sep 2023 18:46:47 GMT</pubDate>
            <atom:updated>2023-09-19T18:54:52.801Z</atom:updated>
            <content:encoded><![CDATA[<p>We’ve refreshed our <a href="https://flow.org/en/docs/">documentation</a>, and added the ability to configure options and lints in <a href="https://flow.org/try/">Try Flow</a>!</p><h4>Documentation</h4><p>Over the past 6 months, we’ve reviewed and updated almost every page of our <a href="https://flow.org/en/docs/">documentation</a>, and added new docs for features previously missing. If you’ve looked at our docs in the past and found them outdated, now is the time to take another look!</p><p>Some page highlights:</p><ul><li>The <a href="https://flow.org/en/docs/lang/refinements/">page on refinements</a> has been completely redone to explain the different ways you can refine.</li><li>We’ve added a page visualizing our <a href="https://flow.org/en/docs/lang/type-hierarchy/">type hierarchy</a>:</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*-FY6CARAa-bToGpo" /></figure><p>After we <a href="https://medium.com/flow-type/exact-object-types-by-default-by-default-cc559af6f69">enabled exact object types by default</a>, Try Flow and all documentation examples have been updated to use exact object types by default.</p><p>Finally, our website is now built with <a href="https://docusaurus.io/">Docusaurus</a> — this should make loading and navigation snappy.</p><h4>Try Flow</h4><p><a href="https://flow.org/try/">Try Flow</a> now allows you to enable and disable options and Flow lints! This configuration is saved in the link you share (along with the Flow version you’ve selected). Select the “Config” tab on <a href="https://flow.org/try/">flow.org/try</a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*TsOrRUxp2_lcD6wd" /></figure><p>We’ll warn you if you open a link specifying an older version of Flow.</p><p>$FlowFixMe suppression comments and types now work in Try Flow.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5da5e4831b5e" width="1" height="1" alt=""><hr><p><a href="https://medium.com/flow-type/improved-flow-docs-and-try-flow-5da5e4831b5e">Improved Flow Docs and Try Flow</a> was originally published in <a href="https://medium.com/flow-type">Flow</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Announcing 5 new Flow tuple type features]]></title>
            <link>https://medium.com/flow-type/announcing-5-new-flow-tuple-type-features-ff4d7f11c50a?source=rss----ab067ae921ed---4</link>
            <guid isPermaLink="false">https://medium.com/p/ff4d7f11c50a</guid>
            <category><![CDATA[flowtype]]></category>
            <category><![CDATA[javascript]]></category>
            <dc:creator><![CDATA[George Zahariev]]></dc:creator>
            <pubDate>Thu, 17 Aug 2023 19:56:22 GMT</pubDate>
            <atom:updated>2023-08-17T19:56:22.605Z</atom:updated>
            <content:encoded><![CDATA[<p>Tuples are a lighter weight alternative to objects when you want to group data, by using positions rather than property names to distinguish elements. However, tuple types have lacked many useful features object types provide - until now!</p><ol><li>Labeled tuple elements: type T = [foo: number, bar: string]</li><li>Variance (read-only/write-only) annotations for tuple elements: type T = [+foo: number, -bar: string]</li><li>Optional tuple elements: type T = [foo?: number, bar?: string]</li><li>Tuple spread type T = [number, string, ...OtherTuple]</li><li>Refinement on tuple length</li></ol><p>Read the full <a href="https://flow.org/en/docs/types/tuples/">docs</a>.</p><h3>Labeled tuple elements</h3><p>You can now add a label to tuple elements. Labels do not affect the type of the tuple element, but are useful in self-documenting the purpose of the tuple elements, especially when multiple elements have the same type.</p><pre>type Range = [x: number, y: number];</pre><p>Labels are also necessary to add variance annotations or optionality modifiers to elements.</p><h3>Variance annotations on tuple elements and read-only tuples</h3><p>You can add <a href="https://flow.org/en/docs/lang/variance/">variance</a> annotations (to denote read-only/write-only) on labeled tuple elements, just like on object properties:</p><pre>type T = [+foo: number, -bar: string];</pre><p>This allows you to mark elements as read-only or write-only. For example:</p><pre>function f(readOnlyTuple: [+foo: number, +bar: string]) {<br>  const n: number = readOnlyTuple[0]; // OK to read<br>  readOnlyTuple[1] = 1; // ERROR! Cannot write<br>}</pre><p>You can also use the $ReadOnly on tuple types as a shorthand for marking each property as read-only:</p><pre>type T = $ReadOnly&lt;[number, string]&gt;; // Same as `[+a: number, +b: string]`</pre><h3>Optional tuple elements</h3><p>You can mark tuple elements as optional with ? after an element’s label. This allows you to omit the optional elements. Optional elements must be at the end of the tuple type, after all required elements.</p><pre>type T = [foo: number, bar?: string];<br>([1, &quot;s&quot;]: T); // OK: has all elements<br>([1]: T); // OK: skipping optional element</pre><p>You cannot write undefined to the optional element - add | void to the element type if you want to do so:</p><pre>type T = [foo?: number, bar?: number | void];<br>declare const x: T;<br>x[0] = undefined; // ERROR<br>([undefined]: T); // ERROR<br><br>x[1] = undefined; // OK: we&#39;ve added `| void` to the element type</pre><p>You can also use the Partial and Required utility types to make all elements optional or required respectively:</p><pre>type AllRequired = [number, string];<br>([]: Partial&lt;AllRequired&gt;); // OK: like `[a?: number, b?: string]` now<br><br>type AllOptional = [a?: number, b?: string];<br>([]: Required&lt;AllOptional&gt;); // ERROR: like `[a: number, b: string]` now</pre><p>Tuples with optional elements have an arity (length) that is a range rather than a single number. For example, [number, b?: string] has an length of 1-2.</p><h3>Tuple type spread</h3><p>You can spread a tuple type into another tuple type to make a longer tuple type:</p><pre>type A = [number, string];<br>type T = [...A, boolean]; // Same as `[number, string, boolean]`<br>([1, &quot;s&quot;, true]: T); // OK</pre><p>Tuple spreads preserve variance and optionality. You cannot spread arrays into tuples, only other tuples.</p><h3>Refinement on length</h3><p>You can refine a union of tuples by their length:</p><pre>type Union = [number, string] | [boolean];<br>function f(x: Union) {<br>  if (x.length === 2) {<br>    // `x` is `[number, string]`<br>    const n: number = x[0]; // OK<br>    const s: string = x[1]; // OK<br>  } else {<br>    // `x` is `[boolean]`<br>    const b: boolean = x[0];<br>  }<br>}</pre><p>Technically this is not a newly added feature, but one not previously announced.</p><h3>Adoption</h3><p>To use labeled tuple elements (including optional elements and variance annotations on elements) and tuple spread elements, you need to upgrade your infrastructure so that it supports the syntax:</p><ul><li>flow and flow-parser: 0.212.0</li><li>prettier: 3</li><li>babel with babel-plugin-syntax-hermes-parser. See <a href="https://flow.org/en/docs/tools/babel/">our Babel guide</a> for setup instructions.</li><li>eslint with hermes-eslint. See <a href="https://flow.org/en/docs/tools/eslint/">our ESLint guide</a> for setup instructions.</li></ul><h3>Bonus: declare const &amp; declare let</h3><p>Flow now supports declare const and declare let (in addition to the existing declare var). These allow you to declare a variable with a type, but without an implementation. They are useful for writing library definitions or creating reproductions of issues in Try Flow, while using the modern const and let instead of the legacy var. Both declare const and declare let are block-scoped, like their non-declare equivalents.</p><pre>if (cond) {<br>  declare const foo: number;<br>}<br>foo; // ERROR: cannot resolve `foo` (as it&#39;s block-scoped)</pre><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ff4d7f11c50a" width="1" height="1" alt=""><hr><p><a href="https://medium.com/flow-type/announcing-5-new-flow-tuple-type-features-ff4d7f11c50a">Announcing 5 new Flow tuple type features</a> was originally published in <a href="https://medium.com/flow-type">Flow</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>