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

[Toolchain] Add emission-related package.json scripts #109

Merged
merged 2 commits into from
Nov 20, 2018

Conversation

damassi
Copy link
Member

@damassi damassi commented Oct 3, 2018

Adds a few new cli commands to make working in Emission a bit easier in the absence being able to yarn link changes between modules:

yarn compile:emission
yarn watch:emission

The flow when working is to start emission and then run, in a second pane, yarn watch:emission which will then start the emitDeclaration + compile process. Changes are reflected instantly:

yess

(Note: This presumes that an /emission folder exists alongside /palette on the developer's HD)

@artsyit
Copy link
Contributor

artsyit commented Oct 3, 2018

Deploy preview for artsy-palette ready!

Built with commit b99aeba

https://deploy-preview-109--artsy-palette.netlify.com

@@ -56,7 +57,9 @@ export interface BoxProps
* Box is just a `View` or `div` (depending on the platform) with common styled-systems
* hooks.
*/
export const Box = primitives.View.attrs<BoxProps>({})`
export const Box: StyledComponentClass<any, any, any> = primitives.View.attrs<
Copy link
Member Author

@damassi damassi Oct 4, 2018

Choose a reason for hiding this comment

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

@alloy, @orta :

Spent a long long time debugging why we were getting type issues in Emission, but this seems to fix it (though in unsatisfactory way).

Some background:

We started using universal components such as <Flex> and <Spacer> in Emission in 2.11.0, which is where emission currently is at, and is the last version that type-checks properly. Around this time I started organizing palette and moving stuff over from Reaction, and then it started to pick up steam with the rest of the team and ton of additions have been made since then. Looping back today I wanted to make sure that our universal implementation still worked and found all kinds of errors related to the styled components output changing in the emitted .d.ts files.

In 2.11.0, this is the output:

export declare const Box: import("styled-components").StyledComponentClass<any, any, any>;

However, somewhere along the way, and after a few dependency changes, this is now the output:

export declare const Box: StyledComponentClass<Pick<{}, never> & Pick<ClassAttributes<HTMLDivElement> & HTMLAttributes<HTMLDivElement> & FlexProps, "alignContent" | "alignItems" | ... and the rest of the dom ... >>;

Thinking further, now that these types have been filled out on the styled-components.d.ts side of things (maybe since they moved to @types/styled-components, which we're now using in palette?) I'm not sure how we could get this to properly type-check given the fact that

import { styled as primitives } from "../../platform/primitives"
...

export const Box = primitives.View`
  ...
`

is platform-dependent code -- meaning that when RN encounters this import, it would see .ios in the filename (platform/primitives -> platform/primitives.ios.tsx) and conditionally import the correct file (and ideally the correct types); however, with tsc we can't set up conditional paths like this, and so from Emission it sees the platform/primitives import and thus fails since we're typechecking against web specific code rather than the correct .ios.tsx counterpart.

I'm at a loss as to how to address this in a future-proof sort of way. (I could also very well have found myself in lost in a maze and missing something somewhere.)

If you pull down this branch and remove these any's from the following code its easy to reproduce the error from emission after running yarn watch:emission from here, waiting till its done compiling, and then starting yarn type-check from the emission folder.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yep - this is definitely something I've been wondering about.

Digging around, microsoft/TypeScript#8328 seems like the best description on the problems, and microsoft/TypeScript#21926 is the best open request for path resolving.

I wonder if it makes sense for us to move Emission (and Palette?) to use a TSC fork that includes this commit: acoates-ms/TypeScript@f023961

For palette checking we can have two tsconfigs - one for RN with extensions, and and for web as vanilla, so CI would compile twice.

Copy link
Contributor

@alloy alloy Oct 4, 2018

Choose a reason for hiding this comment

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

We should have separate TS configs for platforms anyways, because e.g. we can’t have @types/node in a RN project and various other web only typings, nor can we have @types/react-native for web projects.

So what if we just decide to always add the platform extension when a component needs platform specific implementations? i.e. MahComponent.web.tsx and MahComponent.ios.tsx. That way we can just add those patterns to the TS config exclude patterns. i.e. "exclude": ["src/**/*.ios.*"] and "exclude": ["src/**/*.web.*"]

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah but wait, that still wouldn’t fix platform specific imports 🤔

Copy link
Member Author

Choose a reason for hiding this comment

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

cc @ds300 - adding David to the thread since he has a lot of experience in this domain!

Copy link
Contributor

Choose a reason for hiding this comment

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

This might be a good topic to present at Show & Tell, to get more eyes on the problem 👍

export const Box: StyledComponentClass<any, any, any> = primitives.View.attrs<
BoxProps
>({})`
export const Box = primitives.View.attrs<BoxProps>({})`
Copy link
Member Author

Choose a reason for hiding this comment

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

Does

export const Box = primitives.View<BoxProps>`
 ...
`

work?

Copy link
Contributor

Choose a reason for hiding this comment

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

It should

export const Flex: StyledComponentClass<any, any, any> = primitives.View.attrs<
FlexProps
>({})`
export const Flex = primitives.View.attrs<FlexProps>({})`
Copy link
Member Author

Choose a reason for hiding this comment

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

Same here (would you mind updating other definitions too while you're at it?)

@javamonn
Copy link
Contributor

javamonn commented Nov 6, 2018

I've pushed a commit that removes the any cast and adds some missing ios stub components. I don't understand what changed, but note that palette currently typechecks in emission: see yarn ci passing in artsy/emission#1215. The stub components added here are needed as otherwise emission throws runtime errors.

This works for me locally but I'd appreciate others sanity-checking this as it does seem strange to me - I'd appreciate if someone involved in earlier discussions (@damassi, @orta , @l2succes, @alloy) could take a look?

To test this out, from this branch:

  1. Compile palette, copy to emission's node_modules: yarn compile:emission
  2. From emission, it should type check: yarn type-check
    2a. It'll actually fail type-check as-is, but you should be able to remove the missing alignSelf prop to resolve the error: https://github.com/artsy/emission/pull/1215/files#diff-08bdd43785cf0f033df1fee3ee69d0beL14
  3. From emission, it should run without errors: yarn start

}

const Tip = styled(BorderBox)`
const Tip = styled(BorderBox)<TipProps>`
Copy link
Member Author

Choose a reason for hiding this comment

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

@javamonn - right on, ty for updating everything 👍

@javamonn
Copy link
Contributor

javamonn commented Nov 6, 2018

To expand, the component types here are non-ideal and DOM-centric as TS doesn't pick up the platform specific implementation:

export declare const Box: import("styled-components").StyledComponentClass<React.ClassAttributes<HTMLDivElement> & React.HTMLAttributes<HTMLDivElement> & BoxProps, any, React.ClassAttributes<HTMLDivElement> & React.HTMLAttributes<HTMLDivElement> & BoxProps>;

This is something that could still be improved in the future per the discussion above, https://github.com/artsy/palette/pull/109#pullrequestreview-161474475. What's strange to me is why this type-checks in Emission now when it didn't when this PR was originally opened.

These types are also a potential footgun in context of emission, as I think TS would let you pass a DOM specific prop (e.g. className), and that would blow up at runtime? But regardless, it's better than any casting.

@damassi
Copy link
Member Author

damassi commented Nov 6, 2018

@javamonn

screen shot 2018-11-06 at 2 35 52 pm

¯_(ツ)_/¯

@damassi
Copy link
Member Author

damassi commented Nov 6, 2018

Oh! Update:

When running

  • palette $ yarn watch:emission
  • emission $ yarn type-check-w

It produces this error:

screen shot 2018-11-06 at 2 38 34 pm

(I'm certain that overflow: hidden is supported but that seem tangential)

@javamonn
Copy link
Contributor

javamonn commented Nov 7, 2018

@damassi Ah, I see these as well. These both look like minor fixable errors, the second one is expected and requires a change on emission, which we can do as part of upgrading once this PR is merged.

The first one I think I understand what's going on, but not sure how to fix: BorderBox extends Flex, but FlexProps doesn't include props from the underlying primitives.View, so the consumer (Emission in this case) doesn't know that a style prop would be passed down to the primitive view. Is there a way we could include the underlying primitive props - I think this is ReactNative.ViewProperties? Though, because platform specific types don't work yet, we would want to include something like React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement> I think.

Perhaps the underlying primitive prop types could be exported from primitives, or is there a way we can get the full prop types from a component? In the case of BorderBox -> Flex, could we unwrap Flex from:

const Flex: StyledComponentClass<ClassAttributes<HTMLDivElement> & HTMLAttributes<HTMLDivElement> & FlexProps, any, ClassAttributes<HTMLDivElement> & HTMLAttributes<HTMLDivElement> & FlexProps>

to the prop type: ClassAttributes<HTMLDivElement> & HTMLAttributes<HTMLDivElement> & FlexProps ...

Thanks for taking a look!

Copy link
Contributor

@ashfurrow ashfurrow left a comment

Choose a reason for hiding this comment

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

Nice! Thanks for cleaning up those generic types, too 💯

@javamonn
Copy link
Contributor

@l2succes and I paired on this for a bit and the first error noted by @damassi above was resolved by fixing a typo in the type parameterization on BorderBox. The other error (as well as one additional recently introduced error) have fixes over in Emission: artsy/emission#1215.

This PR should be good to merge.

As a follow up, we'll work on figuring out how to ship RN palette types to Emission instead the current DOM based types as noted here.

@l2succes l2succes merged commit 16e3ed9 into artsy:master Nov 20, 2018
@artsyit
Copy link
Contributor

artsyit commented Nov 20, 2018

🎉 This PR is included in version 2.21.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants