ds300 / react-native-typescript-transformer

Seamlessly use TypeScript with React Native
MIT License
657 stars 50 forks source link

Got RN-Web platform-specific file extensions working manually, how could we automate this? #43

Open mosesoak opened 6 years ago

mosesoak commented 6 years ago

Hi, thanks for this excellent project, makes setting up RN + TS a lot easier!

I've integrated this with React Native Web which supports file splitting by extension (.web.tsx / .native.tsx / .ios.tsx / .android.tsx). However, Typescript doesn't play nicely with that piece of magic.

I opened a similar issue at the RNW repo asking if anyone has the know-how to write a piece of magic that would get this under the hood? Or is this something that's already supportable?

Demo of my (hacky) system: https://github.com/mosesoak/react-native-web-ts-app

mosesoak commented 6 years ago

^ made the repo public 😬

skellock commented 6 years ago

My brain broke on this problem as well. The packager(s) are pacified, but TS isn't.

Thankfully, I was only writing a proof-of-concept prototype, but here's how I got around this.

Introducing...

Sadly-Typed Components

Say you're building the <Multi /> component.

Make it a directory that has it's contents look like this:

image

index.ts looks like this:

export * from './multi'

But you see how there's no .web.tsx? That's because the web version is .tsx. In fact, you want to not have .native.tsx as long as you can hold out.

For example: here's what most components should strive to look like:

image

Using Sadly-Typed Components

And here's how you use those components:

import { Multi } from "../some/path/to/multi"

Why These Are Sadly-Typed

It forces you to have the same public interface between both platforms. I ran into TS problems as soon I started doing things like: "ohai native component! you get an extra prop!".

TS is unlikely to get a solution to this as conditional imports goes against their whole #static-4-lyfe design.

This whole approach is wrong and you will burn in hell if you do it.

But, if nobody is watching you... this works well.

If you find the right wayâ„¢, please let me know. I will email you a beer.

mosesoak commented 6 years ago

@skellock cool, thanks for sharing your system! Mine does indeed let you use platform specific extensions, like .web.tsx / .native.tsx. Check out my example repo!

What I'm struggling to figure out is how we could get TS to support this magic, possibly via an npm module. The problem is that prior to compiling to a platform, even if TS was aware of the special imports it still has no idea which path to follow to do its type checking. In reality it would be a union type of all of the various files' contents.

Perhaps I should start discussing this with the TS authors, was hoping to find someone who would know how to write this as a 3rd-party extension.

ds300 commented 6 years ago

Sadly-Typed Components

:joy:

Not sure how to automate this. I think it would require a new TypeScript module resolution strategy which extends node. I imagine the MS folks would be OK with including something like that, they've made plenty of concessions for the React ecosystem already.

mosesoak commented 6 years ago

Cool. I've been able to simplify the system to just use index files without the weird shim file, retry the repo link above to see changes. Closing this issue here since I'd need to take this up with the Typescript team to get further with it

liamjones commented 6 years ago

@mosesoak Thanks for the workaround, using it for now. Was there a ticket raised on the TS repo I can follow regarding the changes discussed above?

ds300 commented 6 years ago

@liamjones I found some discussion here: https://github.com/Microsoft/TypeScript/issues/8328