You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Allow passing additional SupportedExtensions to support React Native .android and .ios module loading #8328
We are using TypeScript to write our React Native application and encountered an issue with platform specific extensions provided by RN.
React Native will detect when a file has a .ios. or .android. extension and load the right file for each platform when requiring them from other components.
For example, you can have these files in your project:
BigButton.ios.js
BigButton.android.js
With this setup, you can just require the files from a different component without paying attention to the platform in which the app will run.
import BigButton from './components/BigButton';
When we use tsc to compile our code, it won't recognize the android or ios platform extension. What about have a customPlatform option that's similar to allowJs that auto prepend the platform name to supportedTypeScriptExtensions?
Do not think globs will help here. the suggesion in the OP seems like a valid one. we should allow additional lookup locations, so that users can specify that, so "additionalExtensions" : [ "ios.ts", "ios.tsx", "android.ts", "android.tsx" ].
the workaround for now, would be create a .d.ts file next to your platform specific modules, something like:
this way your import for ./components/BigButton will resolve to ./components/BigButton.d.ts at design time getting you the shape of the module. and at runtime, it should do the right thing and bind to the platform specific version. there should not be any additional changes required.
Reacted by Saul Shanabrook, Anil Gullapalli, Ryan Thomas, Tanase Hagi and Ryan
changed the title [-]React Native .android and .ios support[/-][+]Allow passing additional SupportedExtensions to support React Native .android and .ios module loading[/+]on Apr 27, 2016
Mohamed Hegazy (@mhegazy) If the exported types in BigButton.android.tsx diverges accidentally from BigButton.ios.tsx, then this won't be picked up at compile time, correct?
Is it possible to keep full compile time type checking?
The compiler does not know that BigButton.android.tsx and BigButton.ios.tsx are two implementation of the same module, and thus, should have the same shape. so they could diverge.
One possible solution here is to have modules implement interfaces, as previously suggested in #420. This will force the compiler to check the shape of the module against an interface.
import*asiosfrom"./BigButton.ios";import*asandroidfrom"./BigButton.ios";declarevar_test: typeofios;declarevar_test: typeofandroid;/// export to get the shape of the moduleexport*from"./BigButton.ios";
now if ios and android ever diverge, you will get an error on the redeclaration of _test. no code will be generated for this.
this will tell the compiler when resolving an import to BigButton to look at:
BigButton.tsx
BigButton.ios.tsx
BigButton.androdid.tsx
For checking that the different implementation for the modules all have the same shape is tracked by #420
Reacted by Arthur Wang and Saul Shanabrook
Reacted by Cameron Little, Vitaliy Ponomarev, Ian MacLeod, Aryeh Stiefel, Bruno Lemos, Mehdi Gloub, Kyle Roach, Seun Lanlege, Ryan, Lorne Chen and 1 more
Mohamed Hegazy (@mhegazy) As far as I can tell (when testing it) the path mapping solution only applies to non-relative imports. So I cannot import A from '../otherfolder/stuff'. Am I missing something obvious here? Any help is appreciated
Reacted by Benjamin Rau, David Xiao, Haythem OUEDERNI, Pavlo Kochubei, Jeremi Stadler, Cameron Little, Jared Russell, Jack Cuthbert, Mitch Crowe, Oscar Franco and 10 more
Can't believe this issue still persists. The idea of allowing custom extension, or more specifically a filename suffix support, with ts or tsx at the end as in file.suffix.ts would be a great plus to the language.
Mohamed Hegazy (@mhegazy) This was closed in favour of #420, but as sondremare mentioned the "paths" option doesn't work for relative imports, and #420 doesn't cover that. Any plans to address it?
Reacted by Sverre Johansen, Robbert van der Helm and Bruno Lemos
i think that at this point the "umbrella" solution is the way to go.
On our index files we should tell to the compiler which components are needed at compile time.
having something like this on my index file (that is platform specific) for me makes sense: index.ios.ts: export * from "./BigButton.ios";
index.android.ts: export * from "./BigButton.android";
Note that with webpack resolve.extensions this isn't necessarily a RN-specific issue, you could, for example have .ltr.tsx and .rtl.tsx variants, or .client.ts and .server.ts for isomorphic apps, etc..., essentially any time you may have multiple output bundles that should be using different code.
Activity
zhengbli commentedon Apr 27, 2016
I think this problem might be better solved with the glob pattern support in tsconfig.json (#5980). Modifying
getSupportedExtensionswouldn't scale.dfguo commentedon Apr 27, 2016
Makes sense. Love to see that change going in soon. Currently blocking our RN project.
mhegazy commentedon Apr 27, 2016
Do not think globs will help here. the suggesion in the OP seems like a valid one. we should allow additional lookup locations, so that users can specify that, so
"additionalExtensions" : [ "ios.ts", "ios.tsx", "android.ts", "android.tsx" ].the workaround for now, would be create a .d.ts file next to your platform specific modules, something like:
this way your import for
./components/BigButtonwill resolve to./components/BigButton.d.tsat design time getting you the shape of the module. and at runtime, it should do the right thing and bind to the platform specific version. there should not be any additional changes required.[-]React Native .android and .ios support[/-][+]Allow passing additional SupportedExtensions to support React Native .android and .ios module loading[/+]saulshanabrook commentedon May 14, 2016
Mohamed Hegazy (@mhegazy) If the exported types in
BigButton.android.tsxdiverges accidentally fromBigButton.ios.tsx, then this won't be picked up at compile time, correct?Is it possible to keep full compile time type checking?
mhegazy commentedon May 14, 2016
The compiler does not know that
BigButton.android.tsxandBigButton.ios.tsxare two implementation of the same module, and thus, should have the same shape. so they could diverge.One possible solution here is to have modules implement interfaces, as previously suggested in #420. This will force the compiler to check the shape of the module against an interface.
mhegazy commentedon May 16, 2016
here is another workaround to get it to type check today, courtesy of Ryan Cavanaugh (@RyanCavanaugh):
now if
iosandandroidever diverge, you will get an error on the redeclaration of_test. no code will be generated for this.mhegazy commentedon May 17, 2016
Recommendations here is to use path mapping support, see https://github.com/Microsoft/TypeScript-Handbook/blob/release-2.0/pages/Module%20Resolution.md#path-mapping
so your tsconfig.json should contain something like:
{ "compilerOptions": { "paths": { "*": ["*", "*.ios", "*.android"] } } }this will tell the compiler when resolving an import to
BigButtonto look at:For checking that the different implementation for the modules all have the same shape is tracked by #420
mhegazy commentedon May 17, 2016
closing in favor of #420
saulshanabrook commentedon May 23, 2016
Mohamed Hegazy (@mhegazy) How can I use the
pathscompiler option? It isn't documented in the Compiler Options documentation.mhegazy commentedon May 23, 2016
Paths is a TS 2.0 feature. documentation is available at: https://github.com/Microsoft/TypeScript-Handbook/blob/release-2.0/pages/Module%20Resolution.md#path-mapping
should be merged in main documentation once 2.0 ships out.
sondremare commentedon Oct 26, 2016
Mohamed Hegazy (@mhegazy) As far as I can tell (when testing it) the path mapping solution only applies to non-relative imports. So I cannot
import A from '../otherfolder/stuff'. Am I missing something obvious here? Any help is appreciatedAdded NavigationBackAndroid to public api
dccarmo commentedon Jul 18, 2017
Having the same issue as sondremare. Is there an updated recommended way to deal with this particular RN feature?
eldenpark commentedon Aug 25, 2017
Can't believe this issue still persists. The idea of allowing custom extension, or more specifically a filename suffix support, with
tsortsxat the end as infile.suffix.tswould be a great plus to the language.sharplet commentedon Sep 28, 2017
Mohamed Hegazy (@mhegazy) This was closed in favour of #420, but as sondremare mentioned the
"paths"option doesn't work for relative imports, and #420 doesn't cover that. Any plans to address it?mhegazy commentedon Oct 5, 2017
it is not clear what path mapping means with a relative path. so no plans really.,
tommasoresti commentedon Dec 15, 2017
i think that at this point the "umbrella" solution is the way to go.
On our index files we should tell to the compiler which components are needed at compile time.
having something like this on my index file (that is platform specific) for me makes sense:
index.ios.ts:
export * from "./BigButton.ios";index.android.ts:
export * from "./BigButton.android";simonbuchan commentedon Jan 15, 2018
Note that with webpack
resolve.extensionsthis isn't necessarily a RN-specific issue, you could, for example have.ltr.tsxand.rtl.tsxvariants, or.client.tsand.server.tsfor isomorphic apps, etc..., essentially any time you may have multiple output bundles that should be using different code.