Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Typescript: improve enum types and setMargin type #1233

Closed
wants to merge 1 commit into from

Conversation

bbohlender
Copy link
Contributor

Currently, it is impossible to write node.setPositionType(2) instead of node.setPositionType(POSITION_TYPE_ABSOLUTE). I understand that the idea is to force explicit usage of the enums. However, declaring type POSITION_TYPE_ABSOLUTE = 2 & ['POSITION_TYPE'] artificially limits use cases, where, for example, the state should be serialized typesafe.

Additionally, this PR fixes the incorrect typing of setMargin(edge: Edge, margin: number) by extending the type to margin: number | string

Copy link
Contributor

@NickGerleman NickGerleman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently, it is impossible to write node.setPositionType(2) instead of node.setPositionType(POSITION_TYPE_ABSOLUTE). I understand that the idea is to force explicit usage of the enums. However, declaring type POSITION_TYPE_ABSOLUTE = 2 & ['POSITION_TYPE'] artificially limits use cases, where, for example, the state should be serialized typesafe.

This was an intentional design decision, so that the underlying data type is opaque/an implementation detail. It also avoids issues like enum types being exposed on hover as entities like 0 | 1 | 2, or being able to plug any enum into any method (it removes the type safety).

If you are wanting to serialize these enums externally, I would recommend adding something like a switch/case over whatever format you are using. I.e. do the mapping yourself from the number to the proper opaque type.

@bbohlender
Copy link
Contributor Author

On the typescript version, I am currently at (4.9.5); typescript offers no options on hover/autocomplete (I wonder if this is preferred over offering 0 | 1 | 2).
Using the enums from typescript would make sense here since they would be present when hovering/autocompleting and would look like: node.setAlignItems(Align.ALIGN_AUTO). The constants could still be exported via export ALIGN_AUTO = Align.ALIGN_AUTO to not break anything.

Nevertheless, I reverted the changes, so this PR only includes the type fix for setMargin :)

@NickGerleman
Copy link
Contributor

Using the enums from typescript would make sense here since they would be present when hovering/autocompleting and would look like: node.setAlignItems(Align.ALIGN_AUTO). The constants could still be exported via export ALIGN_AUTO = Align.ALIGN_AUTO to not break anything.

I think this is a good solution, with the caveat that the TypeScript enums are a runtime concept, and the underlying source is not currently TypeScript. I am not sure if it can be kosher to replicate the same structure in JS, then expose in typings as an enum, or if we really should be making the source TypeScript to do that.

It seems like const enum has well defined runtime semantics that could be matched (and usable from vanilla JS):

  1. https://babeljs.io/docs/babel-plugin-transform-typescript#optimizeconstenums
  2. https://www.typescriptlang.org/docs/handbook/enums.html#const-enums

@@ -135,7 +135,7 @@ export type Node = {
setHeightPercent(height: number): void,
setJustifyContent(justifyContent: Justify): void,
setGap(gutter: Gutter, gapLength: number): Value,
setMargin(edge: Edge, margin: number): void,
setMargin(edge: Edge, margin: number | string): void,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This matches the other types here (converted from previous flowtype typings), but we could also replace this + others with a template literal type for better safety (added in TS 4.1, which is the oldest supported by DefinitelyTyped).

Suggested change
setMargin(edge: Edge, margin: number | string): void,
setMargin(edge: Edge, margin: number | 'auto' | `${number}%`): void,

@facebook-github-bot
Copy link
Contributor

@NickGerleman has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator.

@facebook-github-bot
Copy link
Contributor

@NickGerleman merged this pull request in c09405d.

jeetiss added a commit to shuding/yoga-wasm-web that referenced this pull request Mar 12, 2023
This was referenced Mar 12, 2023
jeetiss added a commit to shuding/yoga-wasm-web that referenced this pull request Mar 12, 2023
facebook-github-bot pushed a commit that referenced this pull request Mar 14, 2023
Summary:
- format types with `prettier`
- apply suggestion from #1233 (comment)

Pull Request resolved: #1236

Reviewed By: javache

Differential Revision: D44052580

Pulled By: NickGerleman

fbshipit-source-id: 0d9810da460cf4290e15308acdbb705c71f8d8a1
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.

None yet

3 participants