|
| 1 | +import useBaseUrl from "@docusaurus/useBaseUrl"; |
| 2 | + |
| 3 | +# Type Safety |
| 4 | + |
| 5 | +## A Tale of Two Type Systems |
| 6 | + |
| 7 | +React Native is built on JavaScript, which does not have a type system. This is |
| 8 | +a problem, because React Native is a large, complex platform. Without a type |
| 9 | +system, developers can't easily reason about the source code or use static |
| 10 | +analysis tools to find bugs. |
| 11 | + |
| 12 | +When developers at Meta created React Native, they chose their own type system |
| 13 | +named [Flow](https://flow.org). Many open-source projects at Meta use Flow. It |
| 14 | +is part of their engineering system and culture. Flow is not used much outside |
| 15 | +of Meta. |
| 16 | + |
| 17 | +The JavaScript community has largely embraced |
| 18 | +[TypeScript](https://www.typescriptlang.org). This includes the React Native |
| 19 | +developer community as well. React Native applications are written in |
| 20 | +TypeScript. Integrations with React Native -- plugins, presets, templates, etc |
| 21 | +-- are also written in TypeScript. |
| 22 | + |
| 23 | +The tools in this project are written in TypeScript, too. Further, tools in this |
| 24 | +project which perform type-checking do so using the TypeScript language. |
| 25 | + |
| 26 | +## Platform-Specific Code |
| 27 | + |
| 28 | +React Native introduces the concept of |
| 29 | +[platform-specific extensions](https://reactnative.dev/docs/platform-specific-code#platform-specific-extensions) |
| 30 | +so that developers can write per-platform code in their applications. |
| 31 | +Platform-specific extensions require a specialized module resolver, capable of |
| 32 | +matching a module import to a file such as `<module>.ios.js` or |
| 33 | +`<module>.native.js`. Metro, the React Native bundler, has a resolver which |
| 34 | +supports this. TypeScript does not, making it impossible to properly type-check |
| 35 | +a specific platform, or get accurate Intellisense. |
| 36 | + |
| 37 | +We are actively working with the TypeScript team to |
| 38 | +[expand the resolver](https://github.com/microsoft/TypeScript/pull/48189) to |
| 39 | +enable this scenario. |
| 40 | + |
| 41 | +In the interim, we have a |
| 42 | +[drop-in replacement for `tsc` which supports React Native module resolution](/docs/packages/typescript-react-native-compiler). |
| 43 | +Developers can use it in lieu of direct support from TypeScript. |
| 44 | + |
| 45 | +## Module Substitution |
| 46 | + |
| 47 | +React Native is implemented on many platforms which span several NPM packages. |
| 48 | +`ios` and `android` implementations are in the `react-native` NPM package, which |
| 49 | +is maintained by Meta. `windows` is under `react-native-windows` and `macos` is |
| 50 | +under `react-native-macos`, both of which are maintained by Microsoft. `win32` |
| 51 | +is an Office-specific platform under `@office-iss/react-native-win32`. |
| 52 | + |
| 53 | +`windows`, `macos`, and `win32` are all considered to be |
| 54 | +[out-of-tree platforms](https://microsoft.github.io/react-native-windows/docs/metro-config-out-tree-platforms) |
| 55 | +because they aren't part of the core `react-native` distribution. Each platform |
| 56 | +package is a complete implementation of React Native, and has (or should have) |
| 57 | +associated TypeScript types. |
| 58 | + |
| 59 | +To avoid having "forked" references to the various NPM package names in code, |
| 60 | +developers are encouraged to always use `import 'react-native'`. Metro, the |
| 61 | +React Native bundler, substitutes 'react-native' with the target platform's |
| 62 | +out-of-tree NPM package. For MacOS, `import 'react-native'` becomes |
| 63 | +`import 'react-native-macos'`. |
| 64 | + |
| 65 | +We are working with the TypeScript team to support a similar "module substution" |
| 66 | +mechanism for type-checking and IntelliSense. Emitted code should preserve the |
| 67 | +original module import. |
| 68 | + |
| 69 | +TypeScript support is most beneficial when integrated with an editor like |
| 70 | +VSCode. Seeing platform-specific type-safety errors, during development, helps |
| 71 | +keep bugs out of the shared source tree. |
| 72 | + |
| 73 | +This feature |
| 74 | +[continues to be a work in progress](https://github.com/microsoft/rnx-kit/issues/1273). |
| 75 | + |
| 76 | +## Type-Safe Bundling |
| 77 | + |
| 78 | +Metro, the React Native bundler, supports TypeScript source files, but it only |
| 79 | +transpiles them to JavaScript. Metro does not do any type-checking. |
| 80 | + |
| 81 | +Our CLI combines Metro and TypeScript to solve this problem. Through |
| 82 | +configuration, you can enable type-checking while running the `rnx-bundle` and |
| 83 | +`rnx-start` commands. Warnings and errors from TypeScript appear on the console: |
| 84 | + |
| 85 | +```typescript title="Unused function with missing type information" |
| 86 | +function foo(x) { |
| 87 | + return x + 2; |
| 88 | +} |
| 89 | +``` |
| 90 | + |
| 91 | +<img |
| 92 | + src={useBaseUrl("/img/type-safe-bundling-output.png")} |
| 93 | + alt="Image showing TypeScript errors. Foo is declared but never used. Parameter x implicitly has an 'any' type." |
| 94 | + width="700" |
| 95 | +/> |
| 96 | + |
| 97 | +The [Bundling guide](/docs/guides/bundling) shows you how to enable type-safe |
| 98 | +bundling. |
0 commit comments