Skip to content

[flow-api-translator] Fix translated return type of async functions - #9486

Closed
robhogan wants to merge 1 commit into
facebook:mainfrom
robhogan:robhogan/async-func-returns-promise-void
Closed

[flow-api-translator] Fix translated return type of async functions#9486
robhogan wants to merge 1 commit into
facebook:mainfrom
robhogan:robhogan/async-func-returns-promise-void

Conversation

@robhogan

@robhogan robhogan commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Summary:
Currently, flowToFlowDef (and therefore flowToTSDef) assumes that a function with an unspecified return type returns void.

This isn't true of async functions, which always return a Promise.

eg:

export async function foo() {}

Translates to:

Before

declare export function foo(): void;,

After

declare export function foo(): Promise<void>;,

This fix also covers class methods, fields, object expressions and arrow functions.

Test plan:

yarn test flowToFlowDef
yarn run v1.22.22
$ NODE_OPTIONS="--experimental-vm-modules" jest flowToFlowDef
(node:54215) [MODULE_TYPELESS_PACKAGE_JSON] Warning: Module type of file:///Users/robhogan/w/flow/packages/flow-parser/dist/estree/TransformComponentSyntax.js is not specified and it doesn't parse as CommonJS.
Reparsing as ES module because module syntax was detected. This incurs a performance overhead.
To eliminate this warning, add "type": "module" to /Users/robhogan/w/flow/packages/flow-parser/package.json.
(Use `node --trace-warnings ...` to show where the warning was created)
(node:54215) ExperimentalWarning: VM Modules is an experimental feature and might change at any time
 PASS  flow-api-translator/__tests__/flowToFlowDef-test.js
  flowToFlowDef
    Comments
      ✓ maintain docblock (31 ms)
      ✓ maintain toplevel statement comments (3 ms)
    dependency walking
      ✓ strip unused function (2 ms)
      ✓ keep used TypeAlias (2 ms)
      ✓ keep chain of used TypeAliases (1 ms)
      ✓ keep used TypeAlias with many references (1 ms)
      ✓ strip unused but shadowed deps (2 ms)
      ✓ strip unused but shadowed deps (complex) (5 ms)
    optimization pass
      ✓ strip unused import defs (2 ms)
    ExportNamedDeclaration
      ✓ type specifier (1 ms)
      ✓ type specifier with source (1 ms)
      ✓ value specifier with source
      ✓ all with source (1 ms)
    ExportDefaultDeclaration
      ✓ export default function (1 ms)
      ✓ export default class (1 ms)
      ✓ export default expression (1 ms)
      ✓ export default var
      ✓ export default object expression (2 ms)
      ✓ export default member expression (1 ms)
      ✓ export default object with member expression (1 ms)
    ExportAllDeclaration
      ✓ export basic (1 ms)
    module.exports
      ✓ export basic
    exports.*
      ✓ export basic (1 ms)
    FunctionDeclaration
      ✓ basic (1 ms)
      ✓ sync without return type
      ✓ async without return type
      ✓ with type params (1 ms)
      ✓ with params
      ✓ with rest params (1 ms)
      ✓ with destructured rest params (1 ms)
      ✓ with default params
      ✓ without identifier (1 ms)
      ✓ without identifier with default param (1 ms)
      ✓ with predicates (1 ms)
    TypeAlias
      ✓ basic (1 ms)
      ✓ with type params
    OpaqueType
      ✓ basic (1 ms)
      ✓ basic local (1 ms)
      ✓ with type params
      ✓ with super type (1 ms)
      ✓ with super type and type params
    ImportDeclaration
      ✓ basic (1 ms)
      ✓ type specifiers (1 ms)
    ClassDeclaration
      ✓ property (5 ms)
      ✓ method (5 ms)
      ✓ strips munged underscore members (1 ms)
      ✓ keeps double-underscore members
      ✓ keeps single-char underscore member (1 ms)
      ✓ strips static munged members
      ✓ strips munged members and their unused imports (1 ms)
      ✓ keeps munged members when mungeUnderscores is false (1 ms)
    InterfaceDeclaration
      ✓ property
      ✓ method (1 ms)
      ✓ local
    VariableDeclaration
      ✓ default require of class used as type (1 ms)
      ✓ default require of function used with typeof (1 ms)
      ✓ default require transitive dep (2 ms)
      ✓ default require member access (1 ms)
      ✓ destructured require all specifiers used
      ✓ destructured require strips unused specifiers
      ✓ destructured require with rename (1 ms)
      ✓ unused default require is stripped
      ✓ unused destructured require is stripped (1 ms)
      ✓ mixed default and destructured requires (1 ms)
      ✓ basic type parameter
      ✓ basic typecast (1 ms)
      ✓ prefer type parameter
      ✓ with dependency (1 ms)
      ✓ with imported value
      ✓ with object type (1 ms)
    EnumDeclaration
      ✓ basic (1 ms)
      ✓ local
    DeclareClass
      ✓ basic
      ✓ complex (1 ms)
      ✓ extends member expression (1 ms)
      ✓ extends type cast expression
      ✓ extends as cast expression (1 ms)
      ✓ extends type cast typeof expression (1 ms)
    Expression
      Identifier
        ✓ basic (1 ms)
      ObjectExpression
        ✓ empty
        ✓ methods (5 ms)
        ✓ properties (1 ms)
        ✓ spread (1 ms)
      Literals
        ✓ number (1 ms)
        ✓ string
        ✓ boolean (1 ms)
        ✓ regex (1 ms)
        ✓ null
      TypeCastExpression
        ✓ basic (1 ms)
      AsExpression
        ✓ basic
      FunctionExpression
        ✓ basic (2 ms)
      ArrowFunctionExpression
        ✓ basic (2 ms)
    ComponentDeclaration
      ✓ export (1 ms)
      ✓ export default
      ✓ params (1 ms)
      ✓ params with identifier-safe string literal names use individual params (1 ms)
      ✓ params with non-identifier string literal names use props object
      ✓ params with comments (1 ms)
      ✓ default params
      ✓ rest param (1 ms)
      ✓ params with rest param
      ✓ non-identifier string literal params with rest param (1 ms)
      ✓ non-identifier string literal params with typed rest param (1 ms)
      ✓ destructured rest param
      ✓ renders type
    HookDeclaration
      ✓ basic (1 ms)
      ✓ with params
      ✓ with type params (1 ms)
      ✓ without return type

Test Suites: 1 passed, 1 total
Tests:       109 passed, 109 total
Snapshots:   2 passed, 2 total
Time:        0.333 s, estimated 1 s
Ran all test suites matching flowToFlowDef.

…ared type (void to Promise<void>)

Currently, `flowToFlowDef` (and therefore `flowToTSDef`) assumes that a function with an unspecified return type returns `void`.

This isn't true of `async` functions, which always return a `Promise`.

eg:

```
export async function foo() {}
```
Translates to:

```
declare export function foo(): void;`,
```

```
declare export function foo(): Promise<void>;`,
```

This fix also covers class methods, fields, object expressions and arrow functions.

Test plan:
```
yarn test flowToFlowDef
yarn run v1.22.22
$ NODE_OPTIONS="--experimental-vm-modules" jest flowToFlowDef
(node:54215) [MODULE_TYPELESS_PACKAGE_JSON] Warning: Module type of file:///Users/robhogan/w/flow/packages/flow-parser/dist/estree/TransformComponentSyntax.js is not specified and it doesn't parse as CommonJS.
Reparsing as ES module because module syntax was detected. This incurs a performance overhead.
To eliminate this warning, add "type": "module" to /Users/robhogan/w/flow/packages/flow-parser/package.json.
(Use `node --trace-warnings ...` to show where the warning was created)
(node:54215) ExperimentalWarning: VM Modules is an experimental feature and might change at any time
 PASS  flow-api-translator/__tests__/flowToFlowDef-test.js
  flowToFlowDef
    Comments
      ✓ maintain docblock (31 ms)
      ✓ maintain toplevel statement comments (3 ms)
    dependency walking
      ✓ strip unused function (2 ms)
      ✓ keep used TypeAlias (2 ms)
      ✓ keep chain of used TypeAliases (1 ms)
      ✓ keep used TypeAlias with many references (1 ms)
      ✓ strip unused but shadowed deps (2 ms)
      ✓ strip unused but shadowed deps (complex) (5 ms)
    optimization pass
      ✓ strip unused import defs (2 ms)
    ExportNamedDeclaration
      ✓ type specifier (1 ms)
      ✓ type specifier with source (1 ms)
      ✓ value specifier with source
      ✓ all with source (1 ms)
    ExportDefaultDeclaration
      ✓ export default function (1 ms)
      ✓ export default class (1 ms)
      ✓ export default expression (1 ms)
      ✓ export default var
      ✓ export default object expression (2 ms)
      ✓ export default member expression (1 ms)
      ✓ export default object with member expression (1 ms)
    ExportAllDeclaration
      ✓ export basic (1 ms)
    module.exports
      ✓ export basic
    exports.*
      ✓ export basic (1 ms)
    FunctionDeclaration
      ✓ basic (1 ms)
      ✓ sync without return type
      ✓ async without return type
      ✓ with type params (1 ms)
      ✓ with params
      ✓ with rest params (1 ms)
      ✓ with destructured rest params (1 ms)
      ✓ with default params
      ✓ without identifier (1 ms)
      ✓ without identifier with default param (1 ms)
      ✓ with predicates (1 ms)
    TypeAlias
      ✓ basic (1 ms)
      ✓ with type params
    OpaqueType
      ✓ basic (1 ms)
      ✓ basic local (1 ms)
      ✓ with type params
      ✓ with super type (1 ms)
      ✓ with super type and type params
    ImportDeclaration
      ✓ basic (1 ms)
      ✓ type specifiers (1 ms)
    ClassDeclaration
      ✓ property (5 ms)
      ✓ method (5 ms)
      ✓ strips munged underscore members (1 ms)
      ✓ keeps double-underscore members
      ✓ keeps single-char underscore member (1 ms)
      ✓ strips static munged members
      ✓ strips munged members and their unused imports (1 ms)
      ✓ keeps munged members when mungeUnderscores is false (1 ms)
    InterfaceDeclaration
      ✓ property
      ✓ method (1 ms)
      ✓ local
    VariableDeclaration
      ✓ default require of class used as type (1 ms)
      ✓ default require of function used with typeof (1 ms)
      ✓ default require transitive dep (2 ms)
      ✓ default require member access (1 ms)
      ✓ destructured require all specifiers used
      ✓ destructured require strips unused specifiers
      ✓ destructured require with rename (1 ms)
      ✓ unused default require is stripped
      ✓ unused destructured require is stripped (1 ms)
      ✓ mixed default and destructured requires (1 ms)
      ✓ basic type parameter
      ✓ basic typecast (1 ms)
      ✓ prefer type parameter
      ✓ with dependency (1 ms)
      ✓ with imported value
      ✓ with object type (1 ms)
    EnumDeclaration
      ✓ basic (1 ms)
      ✓ local
    DeclareClass
      ✓ basic
      ✓ complex (1 ms)
      ✓ extends member expression (1 ms)
      ✓ extends type cast expression
      ✓ extends as cast expression (1 ms)
      ✓ extends type cast typeof expression (1 ms)
    Expression
      Identifier
        ✓ basic (1 ms)
      ObjectExpression
        ✓ empty
        ✓ methods (5 ms)
        ✓ properties (1 ms)
        ✓ spread (1 ms)
      Literals
        ✓ number (1 ms)
        ✓ string
        ✓ boolean (1 ms)
        ✓ regex (1 ms)
        ✓ null
      TypeCastExpression
        ✓ basic (1 ms)
      AsExpression
        ✓ basic
      FunctionExpression
        ✓ basic (2 ms)
      ArrowFunctionExpression
        ✓ basic (2 ms)
    ComponentDeclaration
      ✓ export (1 ms)
      ✓ export default
      ✓ params (1 ms)
      ✓ params with identifier-safe string literal names use individual params (1 ms)
      ✓ params with non-identifier string literal names use props object
      ✓ params with comments (1 ms)
      ✓ default params
      ✓ rest param (1 ms)
      ✓ params with rest param
      ✓ non-identifier string literal params with rest param (1 ms)
      ✓ non-identifier string literal params with typed rest param (1 ms)
      ✓ destructured rest param
      ✓ renders type
    HookDeclaration
      ✓ basic (1 ms)
      ✓ with params
      ✓ with type params (1 ms)
      ✓ without return type

Test Suites: 1 passed, 1 total
Tests:       109 passed, 109 total
Snapshots:   2 passed, 2 total
Time:        0.333 s, estimated 1 s
Ran all test suites matching flowToFlowDef.
```
@meta-cla meta-cla Bot added the CLA Signed label Aug 24, 2026
@meta-codesync

meta-codesync Bot commented Aug 24, 2026

Copy link
Copy Markdown

This pull request has been imported. If you are a Meta employee, you can view this in D117179919. (Because this pull request was imported automatically, there will not be any future comments.)

@meta-codesync meta-codesync Bot closed this in c4bbbb8 Aug 24, 2026
@meta-codesync meta-codesync Bot added the Merged label Aug 24, 2026
@meta-codesync

meta-codesync Bot commented Aug 24, 2026

Copy link
Copy Markdown

This pull request has been merged in c4bbbb8.

@robhogan
robhogan deleted the robhogan/async-func-returns-promise-void branch August 25, 2026 13:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant