Skip to content

Forward-uses are treated as uses of external classes #185

@wchargin

Description

@wchargin

In Flow, the following declarations are equivalent:

type Y = number;
type X = {
  y: Y;
}

and

type X = {
  y: Y;
}
type Y = number;

This plugin translates the first one correctly, but in the second one
the attribute y of the PropTypes generated for X refers to Y as if
it were an external class, not a Flow type. In practice, this means that
the attribute is equivalent to y: any. Presumably, this is because the
conversion scans linearly across the file and has not yet encountered
the definition of Y.

This occurs frequently in practice. A structure like

export type CommitData = {
  fileToCommits: {[filename: string]: string[]},
  commits: {[commitHash: string]: Commit},
};
type Commit = {
  author: string,
  stats: {[filename: string]: FileStats},
};
type FileStats = {
  lines: number,
  added: number,
  deleted: number,
};

is perfectly readable, but is turned by this plugin into

var bpfrpt_proptype_CommitData = {
  fileToCommits: PropTypes.objectOf(PropTypes.arrayOf(PropTypes.string.isRequired).isRequired).isRequired,
  commits: PropTypes.objectOf(function () {
    return (typeof Commit === "function" ? PropTypes.instanceOf(Commit).isRequired : PropTypes.any.isRequired).apply(this, arguments);
  }).isRequired
};

which is effectively useless because typeof Commit === "undefined" as
Commit does not exist in the code. To get the right structure, one
must permute the source:

type FileStats = {
  lines: number,
  added: number,
  deleted: number,
};
type Commit = {
  author: string,
  stats: {[filename: string]: FileStats},
};
export type CommitData = {
  fileToCommits: {[filename: string]: string[]},
  commits: {[commitHash: string]: Commit},
};

This is much less readable. The high-level concepts should come first
(why do I care about FileStats if I don’t know that I’m talking about
commits or commit data?). But even discarding claims of readability, the
plugin output is clearly doing the wrong thing: equivalent Flow programs
are being translated different, which shouldn’t be the case.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions