From bb5b1ae57b2adcef66c292904647d2bd79a1ca17 Mon Sep 17 00:00:00 2001 From: Charles Dudley <618478+charlesbdudley@users.noreply.github.com> Date: Mon, 28 Mar 2022 17:04:41 -0700 Subject: [PATCH 1/4] Add TypeScript support in New Architecture/Codegen --- docs/new-architecture-library-intro.md | 50 ++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 7 deletions(-) diff --git a/docs/new-architecture-library-intro.md b/docs/new-architecture-library-intro.md index a80473f7255..d4a93309967 100644 --- a/docs/new-architecture-library-intro.md +++ b/docs/new-architecture-library-intro.md @@ -18,19 +18,21 @@ As the first step to adopting the new architecture, you will start by creating t ### Writing the JavaScript Spec The JavaScript spec defines all APIs that are provided by the native module, along with the types of those constants and functions. -Using a **typed** spec file allows to be intentional and declare all the input arguments and outputs of your native module’s methods. +Using a **typed** spec file allows us to be intentional and declare all the input arguments and outputs of your native module’s methods. :::info -Currently, this guide is written under the assumption that you will be using [Flow](https://flow.org/). The `react-native-codegen` package is also currently working only with Flow source as input. We know that a lot of our users are using **TypeScript** instead and we hope to release TypeScript support really soon. This guide will be updated once the TypeScript support is also available. +JavaScript spec files can be written in either [Flow](https://flow.org/) or [TypeScript](https://www.typescriptlang.org/). The Codegen process will automatically choose the correct type parser based on your spec file's extension (`.js` for Flow, `.ts` or `.tsx` for TypeScript). ::: -#### Turbomodules +#### TurboModules -JavaScript spec files **must** be named `Native.js` and they export a `TurboModuleRegistry` `Spec` object. The name convention is important because the Codegen process looks for modules whose `js` spec file starts with the keyword `Native`. +JavaScript spec files **must** be named `Native.js` (for TypeScript use extension `.ts` or `.tsx`) and they export a `TurboModuleRegistry` `Spec` object. The name convention is important because the Codegen process looks for modules whose JavaScript spec file starts with the keyword `Native`. -The following is a basic JavaScript spec template, written using the [Flow](https://flow.org/) syntax. +The following is a basic JavaScript spec template, written in [Flow](https://flow.org/) as well as [TypeScript](https://www.typescriptlang.org/). + +##### TurboModule: Flow Example ```ts // @flow @@ -48,11 +50,29 @@ export interface Spec extends TurboModule { export default (TurboModuleRegistry.get(''): ?Spec); ``` +##### Turbo Module: TypeScript Example + +```ts +import type { TurboModule } from 'react-native/Libraries/TurboModule/RCTExport'; +import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; + +export interface Spec extends TurboModule { + readonly getConstants: () => {}; + + // your module methods go here, for example: + getString(id: string): Promise; +} + +export default TurboModuleRegistry.get(''); +``` + #### Fabric Components -JavaScript spec files **must** be named `NativeComponent.js` and they export a `HostComponent` object. The name convention is important: the Codegen process looks for components whose `js` spec file ends with the keyword `NativeComponent`. +JavaScript spec files **must** be named `NativeComponent.js` (for TypeScript use extension `.ts` or `.tsx`) and they export a `HostComponent` object. The name convention is important: the Codegen process looks for components whose `js` spec file ends with the keyword `NativeComponent`. + +The following is a basic JavaScript spec template, written in [Flow](https://flow.org/) as well as [TypeScript](https://www.typescriptlang.org/). -The following is a basic JavaScript spec template, written using the [Flow](https://flow.org/) syntax. +##### Fabric Component: Flow Example ```ts // @flow strict-local @@ -71,6 +91,22 @@ export default (codegenNativeComponent( ): HostComponent); ``` +##### Fabric Component: TypeScript Example + +```ts +import type { ViewProps } from 'ViewPropTypes'; +import type { HostComponent } from 'react-native'; +const codegenNativeComponent = require('codegenNativeComponent'); + +export interface NativeProps extends ViewProps { + // add other props here +} + +export default codegenNativeComponent( + '' +) as HostComponent; +``` + ### Supported Flow Types When using Flow, you will be using [type annotations](https://flow.org/en/docs/types/) to define your spec. Keeping in mind that the goal of defining a JavaScript spec is to ensure the generated native interface code is type safe, the set of supported Flow types will be those that can be mapped one-to-one to a corresponding type on the native platform. From d6156c69dae7b85179c14db69e3ab07fd7960819 Mon Sep 17 00:00:00 2001 From: Charles Dudley <618478+charlesbdudley@users.noreply.github.com> Date: Tue, 29 Mar 2022 14:14:07 -0700 Subject: [PATCH 2/4] Updates based on feedback --- docs/new-architecture-library-intro.md | 45 +++++++++++++++++--------- website/core/TabsConstants.js | 8 +++++ 2 files changed, 37 insertions(+), 16 deletions(-) diff --git a/docs/new-architecture-library-intro.md b/docs/new-architecture-library-intro.md index d4a93309967..9fdcb28235a 100644 --- a/docs/new-architecture-library-intro.md +++ b/docs/new-architecture-library-intro.md @@ -4,6 +4,9 @@ title: Prerequisites for Libraries --- import NewArchitectureWarning from './\_markdown-new-architecture-warning.mdx'; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import constants from '@site/core/TabsConstants'; @@ -22,17 +25,18 @@ Using a **typed** spec file allows us to be intentional and declare all the inpu :::info -JavaScript spec files can be written in either [Flow](https://flow.org/) or [TypeScript](https://www.typescriptlang.org/). The Codegen process will automatically choose the correct type parser based on your spec file's extension (`.js` for Flow, `.ts` or `.tsx` for TypeScript). +JavaScript spec files can be written in either [Flow](https://flow.org/) or [TypeScript](https://www.typescriptlang.org/). The Codegen process will automatically choose the correct type parser based on your spec file's extension (`.js` for Flow, `.ts` or `.tsx` for TypeScript). Note that TypeScript support is still in beta—if you come across any bugs or missing features, please [report them](https://github.com/reactwg/react-native-new-architecture/discussions/categories/q-a). ::: #### TurboModules -JavaScript spec files **must** be named `Native.js` (for TypeScript use extension `.ts` or `.tsx`) and they export a `TurboModuleRegistry` `Spec` object. The name convention is important because the Codegen process looks for modules whose JavaScript spec file starts with the keyword `Native`. +JavaScript spec files **must** be named `Native.js` (for TypeScript use extension `.ts` or `.tsx`) and they export a `TurboModuleRegistry` `Spec` object. The name convention is important because the Codegen process looks for modules whose spec file (either JavaScript of TypeScript) starts with the keyword `Native`. -The following is a basic JavaScript spec template, written in [Flow](https://flow.org/) as well as [TypeScript](https://www.typescriptlang.org/). +The following snippets show a basic spec template, written in [Flow](https://flow.org/) as well as [TypeScript](https://www.typescriptlang.org/). -##### TurboModule: Flow Example + + ```ts // @flow @@ -50,11 +54,12 @@ export interface Spec extends TurboModule { export default (TurboModuleRegistry.get(''): ?Spec); ``` -##### Turbo Module: TypeScript Example + + ```ts -import type { TurboModule } from 'react-native/Libraries/TurboModule/RCTExport'; -import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; +import type { TurboModule } from 'react-native'; +import { TurboModuleRegistry } from 'react-native'; export interface Spec extends TurboModule { readonly getConstants: () => {}; @@ -66,13 +71,17 @@ export interface Spec extends TurboModule { export default TurboModuleRegistry.get(''); ``` + + + #### Fabric Components -JavaScript spec files **must** be named `NativeComponent.js` (for TypeScript use extension `.ts` or `.tsx`) and they export a `HostComponent` object. The name convention is important: the Codegen process looks for components whose `js` spec file ends with the keyword `NativeComponent`. +JavaScript spec files **must** be named `NativeComponent.js` (for TypeScript use extension `.ts` or `.tsx`) and they export a `HostComponent` object. The name convention is important: the Codegen process looks for components whose spec file (either JavaScript or TypeScript) ends with the suffix `NativeComponent`. -The following is a basic JavaScript spec template, written in [Flow](https://flow.org/) as well as [TypeScript](https://www.typescriptlang.org/). +The following snippet shows a basic JavaScript spec template, written in [Flow](https://flow.org/) as well as [TypeScript](https://www.typescriptlang.org/). -##### Fabric Component: Flow Example + + ```ts // @flow strict-local @@ -91,12 +100,13 @@ export default (codegenNativeComponent( ): HostComponent); ``` -##### Fabric Component: TypeScript Example + + ```ts import type { ViewProps } from 'ViewPropTypes'; import type { HostComponent } from 'react-native'; -const codegenNativeComponent = require('codegenNativeComponent'); +import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; export interface NativeProps extends ViewProps { // add other props here @@ -107,15 +117,18 @@ export default codegenNativeComponent( ) as HostComponent; ``` -### Supported Flow Types + + + +### Supported Types -When using Flow, you will be using [type annotations](https://flow.org/en/docs/types/) to define your spec. Keeping in mind that the goal of defining a JavaScript spec is to ensure the generated native interface code is type safe, the set of supported Flow types will be those that can be mapped one-to-one to a corresponding type on the native platform. +When using Flow or TypeScript, you will be using [type annotations](https://flow.org/en/docs/types/) to define your spec. Keeping in mind that the goal of defining a JavaScript spec is to ensure the generated native interface code is type safe, the set of supported types will be those that can be mapped one-to-one to a corresponding type on the native platform. -In general, this means you can use primitive types (strings, numbers, booleans), as well as function types, object types, and array types. Union types, on the other hand, are not supported. All types must be read-only in Flow: either `+` or `$ReadOnly<>` or `{||}` objects. +In general, this means you can use primitive types (strings, numbers, booleans), as well as function types, object types, and array types. Union types, on the other hand, are not supported. All types must be read-only. For Flow: either `+` or `$ReadOnly<>` or `{||}` objects. For TypeScript: `readonly` for properties, `Readonly<>` for objects, and `ReadonlyArray<>` for arrays. -> See Appendix [I. Flow Type to Native Type Mapping](#i-flow-type-to-native-type-mapping). +> See Appendix [I. Spec Type to Native Type Mapping](#i-spec-type-to-native-type-mapping). ### Be Consistent Across Platforms and Eliminate Type Ambiguity diff --git a/website/core/TabsConstants.js b/website/core/TabsConstants.js index 5735eb6a105..3687c0b1678 100644 --- a/website/core/TabsConstants.js +++ b/website/core/TabsConstants.js @@ -25,6 +25,12 @@ const androidLanguages = [ ]; const defaultAndroidLanguage = 'java'; +const turboModuleSpecLanguages = [ + {label: 'Flow', value: 'flow'}, + {label: 'TypeScript', value: 'typescript'}, +]; +const defaultTurboModuleSpecLanguage = 'flow'; + const guides = [ {label: 'Expo CLI Quickstart', value: 'quickstart'}, {label: 'React Native CLI Quickstart', value: 'native'}, @@ -59,6 +65,8 @@ export default { defaultPlatform, defaultSyntax, defaultAndroidLanguage, + turboModuleSpecLanguages, + defaultTurboModuleSpecLanguage, getDevNotesTabs, guides, oses, From 6e2f9e66657c81b1a3debf5cb2c08354b637e648 Mon Sep 17 00:00:00 2001 From: Charles Dudley <618478+charlesbdudley@users.noreply.github.com> Date: Tue, 12 Apr 2022 13:30:11 -0700 Subject: [PATCH 3/4] Updated Appendix link with bit about typescript coming soon. --- docs/new-architecture-library-intro.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/new-architecture-library-intro.md b/docs/new-architecture-library-intro.md index 9fdcb28235a..caaac603a5b 100644 --- a/docs/new-architecture-library-intro.md +++ b/docs/new-architecture-library-intro.md @@ -128,7 +128,7 @@ When using Flow or TypeScript, you will be using [type annotations](https://flow In general, this means you can use primitive types (strings, numbers, booleans), as well as function types, object types, and array types. Union types, on the other hand, are not supported. All types must be read-only. For Flow: either `+` or `$ReadOnly<>` or `{||}` objects. For TypeScript: `readonly` for properties, `Readonly<>` for objects, and `ReadonlyArray<>` for arrays. -> See Appendix [I. Spec Type to Native Type Mapping](#i-spec-type-to-native-type-mapping). +> See Appendix [I. Flow Type to Native Type Mapping](./new-architecture-appendix#i-flow-type-to-native-type-mapping). (TypeScript to Native Type Mapping will be added soon.) ### Be Consistent Across Platforms and Eliminate Type Ambiguity From 6f57418d807277e76583007002a805f7027a33c8 Mon Sep 17 00:00:00 2001 From: Charles Dudley <618478+charlesbdudley@users.noreply.github.com> Date: Wed, 13 Apr 2022 13:22:49 -0700 Subject: [PATCH 4/4] Updated constants names for clarification --- docs/new-architecture-library-intro.md | 4 ++-- website/core/TabsConstants.js | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/new-architecture-library-intro.md b/docs/new-architecture-library-intro.md index caaac603a5b..e973a9c5eed 100644 --- a/docs/new-architecture-library-intro.md +++ b/docs/new-architecture-library-intro.md @@ -35,7 +35,7 @@ JavaScript spec files **must** be named `Native.js` (for TypeScript The following snippets show a basic spec template, written in [Flow](https://flow.org/) as well as [TypeScript](https://www.typescriptlang.org/). - + ```ts @@ -80,7 +80,7 @@ JavaScript spec files **must** be named `NativeComponent.js` ( The following snippet shows a basic JavaScript spec template, written in [Flow](https://flow.org/) as well as [TypeScript](https://www.typescriptlang.org/). - + ```ts diff --git a/website/core/TabsConstants.js b/website/core/TabsConstants.js index 3687c0b1678..f94d13b8ed7 100644 --- a/website/core/TabsConstants.js +++ b/website/core/TabsConstants.js @@ -25,11 +25,11 @@ const androidLanguages = [ ]; const defaultAndroidLanguage = 'java'; -const turboModuleSpecLanguages = [ +const javaScriptSpecLanguages = [ {label: 'Flow', value: 'flow'}, {label: 'TypeScript', value: 'typescript'}, ]; -const defaultTurboModuleSpecLanguage = 'flow'; +const defaultJavaScriptSpecLanguages = 'flow'; const guides = [ {label: 'Expo CLI Quickstart', value: 'quickstart'}, @@ -65,8 +65,8 @@ export default { defaultPlatform, defaultSyntax, defaultAndroidLanguage, - turboModuleSpecLanguages, - defaultTurboModuleSpecLanguage, + javaScriptSpecLanguages, + defaultJavaScriptSpecLanguages, getDevNotesTabs, guides, oses,