Browse Source

typescripting

Daniel Zlotin 7 years ago
parent
commit
ce48e0032c

+ 29
- 16
lib/src/Navigation.ts View File

@@ -12,20 +12,33 @@ import { ComponentProvider } from 'react-native';
12 12
 import { Element } from './adapters/Element';
13 13
 
14 14
 class Navigation {
15
-  public readonly Element = Element;
16
-
17
-  private readonly store = new Store();
18
-  private readonly nativeEventsReceiver = new NativeEventsReceiver();
19
-  private readonly uniqueIdProvider = new UniqueIdProvider();
20
-  private readonly componentRegistry = new ComponentRegistry(this.store);
21
-  private readonly layoutTreeParser = new LayoutTreeParser();
22
-  private readonly layoutTreeCrawler = new LayoutTreeCrawler(this.uniqueIdProvider, this.store);
23
-  private readonly nativeCommandsSender = new NativeCommandsSender();
24
-  private readonly commands = new Commands(this.nativeCommandsSender, this.layoutTreeParser, this.layoutTreeCrawler);
25
-  private readonly publicEventsRegistry = new PublicEventsRegistry(this.nativeEventsReceiver);
26
-  private readonly privateEventsListener = new PrivateEventsListener(this.nativeEventsReceiver, this.store);
15
+  public readonly Element;
16
+
17
+  private readonly store;
18
+  private readonly nativeEventsReceiver;
19
+  private readonly uniqueIdProvider;
20
+  private readonly componentRegistry;
21
+  private readonly layoutTreeParser;
22
+  private readonly layoutTreeCrawler;
23
+  private readonly nativeCommandsSender;
24
+  private readonly commands;
25
+  private readonly publicEventsRegistry;
26
+  private readonly privateEventsListener;
27 27
 
28 28
   constructor() {
29
+    this.Element = Element;
30
+
31
+    this.store = new Store();
32
+    this.nativeEventsReceiver = new NativeEventsReceiver();
33
+    this.uniqueIdProvider = new UniqueIdProvider();
34
+    this.componentRegistry = new ComponentRegistry(this.store);
35
+    this.layoutTreeParser = new LayoutTreeParser();
36
+    this.layoutTreeCrawler = new LayoutTreeCrawler(this.uniqueIdProvider, this.store);
37
+    this.nativeCommandsSender = new NativeCommandsSender();
38
+    this.commands = new Commands(this.nativeCommandsSender, this.layoutTreeParser, this.layoutTreeCrawler);
39
+    this.publicEventsRegistry = new PublicEventsRegistry(this.nativeEventsReceiver);
40
+    this.privateEventsListener = new PrivateEventsListener(this.nativeEventsReceiver, this.store);
41
+
29 42
     this.privateEventsListener.listenAndHandlePrivateEvents();
30 43
   }
31 44
 
@@ -108,7 +121,7 @@ class Navigation {
108 121
    * Pop the stack to a given component
109 122
    * @param {string} componentId The component's id.
110 123
    */
111
-  popTo(componentId) {
124
+  popTo(componentId: string) {
112 125
     return this.commands.popTo(componentId);
113 126
   }
114 127
 
@@ -116,7 +129,7 @@ class Navigation {
116 129
    * Pop the component's stack to root.
117 130
    * @param {*} componentId
118 131
    */
119
-  popToRoot(componentId) {
132
+  popToRoot(componentId: string) {
120 133
     return this.commands.popToRoot(componentId);
121 134
   }
122 135
 
@@ -132,12 +145,12 @@ class Navigation {
132 145
    * dismiss overlay by componentId
133 146
    * @param {string} componentId
134 147
    */
135
-  dismissOverlay(componentId) {
148
+  dismissOverlay(componentId: string) {
136 149
     return this.commands.dismissOverlay(componentId);
137 150
   }
138 151
 
139 152
   /**
140
-   * Obtain the events registery instance
153
+   * Obtain the events registry instance
141 154
    */
142 155
   events() {
143 156
     return this.publicEventsRegistry;

+ 5
- 4
lib/src/adapters/Element.tsx View File

@@ -3,13 +3,13 @@ import * as PropTypes from 'prop-types';
3 3
 import { requireNativeComponent } from 'react-native';
4 4
 
5 5
 interface ElementProps {
6
-  elementId;
7
-  resizeMode;
6
+  elementId: PropTypes.Requireable<string>;
7
+  resizeMode: any;
8 8
 }
9 9
 
10
-let RNNElement: React.ComponentClass;
10
+let RNNElement: React.ComponentType<any>;
11 11
 
12
-export class Element extends React.Component<ElementProps, object> {
12
+export class Element extends React.Component<ElementProps, any> {
13 13
   static propTypes = {
14 14
     elementId: PropTypes.string.isRequired,
15 15
     resizeMode: PropTypes.string
@@ -26,3 +26,4 @@ export class Element extends React.Component<ElementProps, object> {
26 26
 }
27 27
 
28 28
 RNNElement = requireNativeComponent('RNNElement', Element);
29
+

+ 1
- 1
lib/src/commands/LayoutTreeParser.ts View File

@@ -42,7 +42,7 @@ export class LayoutTreeParser {
42 42
     if (!api.center) {
43 43
       throw new Error(`sideMenu.center is required`);
44 44
     }
45
-    const children = [];
45
+    const children: Array<LayoutNode> = [];
46 46
     if (api.left) {
47 47
       children.push({
48 48
         type: LayoutType.SideMenuLeft,

+ 0
- 2
lib/src/commands/LayoutType.test.ts View File

@@ -11,8 +11,6 @@ describe.only('LayoutType', () => {
11 11
   });
12 12
 
13 13
   it('isLayoutType', () => {
14
-    expect(isLayoutType(null)).toBe(false);
15
-    expect(isLayoutType(undefined)).toBe(false);
16 14
     expect(isLayoutType('')).toBe(false);
17 15
     expect(isLayoutType('asdasd')).toBe(false);
18 16
     expect(isLayoutType('TopTabs')).toBe(true);

+ 1
- 1
lib/src/components/ComponentRegistry.test.tsx View File

@@ -46,6 +46,6 @@ describe('ComponentRegistry', () => {
46 46
     uut.registerComponent('example.MyComponent.name', () => MyComponent);
47 47
     const Component = mockRegistry.mock.calls[0][1]();
48 48
     const tree = renderer.create(<Component componentId="123" />);
49
-    expect(tree.toJSON().children).toEqual(['Hello, World!']);
49
+    expect(tree.toJSON()!.children).toEqual(['Hello, World!']);
50 50
   });
51 51
 });

+ 0
- 1
lib/src/components/ComponentRegistry.ts View File

@@ -1,4 +1,3 @@
1
-import * as React from 'react';
2 1
 import { AppRegistry, ComponentProvider } from 'react-native';
3 2
 import { ComponentWrapper } from './ComponentWrapper';
4 3
 

+ 18
- 18
lib/src/components/ComponentWrapper.test.tsx View File

@@ -61,21 +61,21 @@ describe('ComponentWrapper', () => {
61 61
     const NavigationComponent = ComponentWrapper.wrap(componentName, MyComponent, store);
62 62
     expect(NavigationComponent).not.toBeInstanceOf(MyComponent);
63 63
     const tree = renderer.create(<NavigationComponent componentId={'component1'} />);
64
-    expect(tree.toJSON().children).toEqual(['Hello, World!']);
65
-    expect(tree.getInstance().originalComponentRef).toBeInstanceOf(MyComponent);
64
+    expect(tree.toJSON()!.children).toEqual(['Hello, World!']);
65
+    expect(tree.getInstance()!.originalComponentRef).toBeInstanceOf(MyComponent);
66 66
   });
67 67
 
68 68
   it('injects props from wrapper into original component', () => {
69 69
     const NavigationComponent = ComponentWrapper.wrap(componentName, MyComponent, store);
70 70
     const tree = renderer.create(<NavigationComponent componentId={'component1'} myProp={'yo'} />);
71
-    expect(tree.getInstance().originalComponentRef.props.myProp).toEqual('yo');
71
+    expect(tree.getInstance()!.originalComponentRef.props.myProp).toEqual('yo');
72 72
   });
73 73
 
74 74
   it('updates props from wrapper into original component', () => {
75 75
     const NavigationComponent = ComponentWrapper.wrap(componentName, MyComponent, store);
76 76
     const tree = renderer.create(<TestParent ChildClass={NavigationComponent} />);
77 77
     expect(childRef.props.foo).toEqual(undefined);
78
-    tree.getInstance().setState({ propsFromState: { foo: 'yo' } });
78
+    tree.getInstance()!.setState({ propsFromState: { foo: 'yo' } });
79 79
     expect(childRef.props.foo).toEqual('yo');
80 80
   });
81 81
 
@@ -83,7 +83,7 @@ describe('ComponentWrapper', () => {
83 83
     store.setPropsForComponentId('component123', { numberProp: 1, stringProp: 'hello', objectProp: { a: 2 } });
84 84
     const NavigationComponent = ComponentWrapper.wrap(componentName, MyComponent, store);
85 85
     const tree = renderer.create(<NavigationComponent componentId={'component123'} />);
86
-    const originalComponentProps = tree.getInstance().originalComponentRef.props;
86
+    const originalComponentProps = tree.getInstance()!.originalComponentRef.props;
87 87
     expect(originalComponentProps).toEqual({ componentId: 'component123', numberProp: 1, stringProp: 'hello', objectProp: { a: 2 } });
88 88
   });
89 89
 
@@ -93,7 +93,7 @@ describe('ComponentWrapper', () => {
93 93
     store.setPropsForComponentId('component1', { myProp: 'hello' });
94 94
     expect(childRef.originalComponentRef.props.foo).toEqual(undefined);
95 95
     expect(childRef.originalComponentRef.props.myProp).toEqual(undefined);
96
-    tree.getInstance().setState({ propsFromState: { foo: 'yo' } });
96
+    tree.getInstance()!.setState({ propsFromState: { foo: 'yo' } });
97 97
     expect(childRef.originalComponentRef.props.foo).toEqual('yo');
98 98
     expect(childRef.originalComponentRef.props.myProp).toEqual('hello');
99 99
   });
@@ -102,15 +102,15 @@ describe('ComponentWrapper', () => {
102 102
     const NavigationComponent = ComponentWrapper.wrap(componentName, MyComponent, store);
103 103
     const tree = renderer.create(<TestParent ChildClass={NavigationComponent} />);
104 104
     expect(childRef.originalComponentRef.props.componentId).toEqual('component1');
105
-    tree.getInstance().setState({ propsFromState: { id: 'ERROR' } });
105
+    tree.getInstance()!.setState({ propsFromState: { id: 'ERROR' } });
106 106
     expect(childRef.originalComponentRef.props.componentId).toEqual('component1');
107 107
   });
108 108
 
109 109
   it('assignes key by id', () => {
110 110
     const NavigationComponent = ComponentWrapper.wrap(componentName, MyComponent, store);
111 111
     const tree = renderer.create(<NavigationComponent componentId={'component1'} />);
112
-    expect(tree.getInstance().originalComponentRef.props.componentId).toEqual('component1');
113
-    expect(tree.getInstance().originalComponentRef._reactInternalInstance.key).toEqual('component1');
112
+    expect(tree.getInstance()!.originalComponentRef.props.componentId).toEqual('component1');
113
+    expect(tree.getInstance()!.originalComponentRef._reactInternalInstance.key).toEqual('component1');
114 114
   });
115 115
 
116 116
   it('saves self ref into store', () => {
@@ -131,14 +131,14 @@ describe('ComponentWrapper', () => {
131 131
   it('holds ref to OriginalComponent', () => {
132 132
     const NavigationComponent = ComponentWrapper.wrap(componentName, MyComponent, store);
133 133
     const tree = renderer.create(<NavigationComponent componentId={'component1'} />);
134
-    expect(tree.getInstance().originalComponentRef).toBeDefined();
135
-    expect(tree.getInstance().originalComponentRef).toBeInstanceOf(MyComponent);
134
+    expect(tree.getInstance()!.originalComponentRef).toBeDefined();
135
+    expect(tree.getInstance()!.originalComponentRef).toBeInstanceOf(MyComponent);
136 136
   });
137 137
 
138 138
   it('cleans ref to internal component on unount', () => {
139 139
     const NavigationComponent = ComponentWrapper.wrap(componentName, MyComponent, store);
140 140
     const tree = renderer.create(<NavigationComponent componentId={'component1'} />);
141
-    const instance = tree.getInstance();
141
+    const instance = tree.getInstance()!;
142 142
     expect(instance.originalComponentRef).toBeInstanceOf(React.Component);
143 143
     tree.unmount();
144 144
     expect(instance.originalComponentRef).toBeFalsy();
@@ -166,16 +166,16 @@ describe('ComponentWrapper', () => {
166 166
     it('didAppear, didDisappear and onNavigationButtonPressed are optional', () => {
167 167
       const NavigationComponent = ComponentWrapper.wrap(componentName, MyComponent, store);
168 168
       const tree = renderer.create(<NavigationComponent componentId={'component1'} />);
169
-      expect(() => tree.getInstance().didAppear()).not.toThrow();
170
-      expect(() => tree.getInstance().didDisappear()).not.toThrow();
171
-      expect(() => tree.getInstance().onNavigationButtonPressed()).not.toThrow();
169
+      expect(() => tree.getInstance()!.didAppear()).not.toThrow();
170
+      expect(() => tree.getInstance()!.didDisappear()).not.toThrow();
171
+      expect(() => tree.getInstance()!.onNavigationButtonPressed()).not.toThrow();
172 172
     });
173 173
 
174 174
     it('calls didAppear on OriginalComponent', () => {
175 175
       const NavigationComponent = ComponentWrapper.wrap(componentName, MyLifecycleComponent, store);
176 176
       const tree = renderer.create(<NavigationComponent componentId={'component1'} />);
177 177
       expect(didAppearCallback).toHaveBeenCalledTimes(0);
178
-      tree.getInstance().didAppear();
178
+      tree.getInstance()!.didAppear();
179 179
       expect(didAppearCallback).toHaveBeenCalledTimes(1);
180 180
     });
181 181
 
@@ -183,7 +183,7 @@ describe('ComponentWrapper', () => {
183 183
       const NavigationComponent = ComponentWrapper.wrap(componentName, MyLifecycleComponent, store);
184 184
       const tree = renderer.create(<NavigationComponent componentId={'component1'} />);
185 185
       expect(didDisappearCallback).toHaveBeenCalledTimes(0);
186
-      tree.getInstance().didDisappear();
186
+      tree.getInstance()!.didDisappear();
187 187
       expect(didDisappearCallback).toHaveBeenCalledTimes(1);
188 188
     });
189 189
 
@@ -191,7 +191,7 @@ describe('ComponentWrapper', () => {
191 191
       const NavigationComponent = ComponentWrapper.wrap(componentName, MyLifecycleComponent, store);
192 192
       const tree = renderer.create(<NavigationComponent componentId={'component1'} />);
193 193
       expect(onNavigationButtonPressedCallback).toHaveBeenCalledTimes(0);
194
-      tree.getInstance().onNavigationButtonPressed();
194
+      tree.getInstance()!.onNavigationButtonPressed();
195 195
       expect(onNavigationButtonPressedCallback).toHaveBeenCalledTimes(1);
196 196
     });
197 197
   });

+ 2
- 2
package.json View File

@@ -69,11 +69,11 @@
69 69
     "shell-utils": "1.x.x",
70 70
     "xo": "0.18.x",
71 71
     "typescript": "2.x.x",
72
-    "@types/react": "16.0.0",
72
+    "@types/react": "16.x.x",
73 73
     "@types/react-native": "0.49.x",
74 74
     "@types/lodash": "4.x.x",
75 75
     "@types/prop-types": "15.x.x",
76
-    "@types/react-test-renderer": "16.0.0",
76
+    "@types/react-test-renderer": "16.x.x",
77 77
     "@types/jest": "22.x.x"
78 78
   },
79 79
   "babel": {

+ 3
- 3
tsconfig-strict.json View File

@@ -10,14 +10,14 @@
10 10
     "importHelpers": true,
11 11
     "noEmitOnError": true,
12 12
     "noFallthroughCasesInSwitch": true,
13
-    "noImplicitAny": true,
14 13
     "noImplicitReturns": true,
15 14
     "noImplicitThis": true,
16 15
     "noUnusedLocals": true,
17 16
     "noUnusedParameters": true,
18 17
     "pretty": true,
19
-    "strictFunctionTypes": false,
18
+    "strictFunctionTypes": true,
20 19
     "strictNullChecks": true,
21
-    "strict": true
20
+    "strict": true,
21
+    "noImplicitAny": true
22 22
   }
23 23
 }

+ 3
- 10
tsconfig.json View File

@@ -1,18 +1,11 @@
1 1
 {
2
+  "extends": "./tsconfig-strict.json",
2 3
   "compilerOptions": {
3 4
     "outDir": "./lib/dist",
4
-    "allowJs": true,
5
+    "allowJs": false,
5 6
     "target": "esnext",
6 7
     "module": "commonjs",
7
-    "jsx": "react-native",
8
-    "types": [
9
-      "lodash",
10
-      "react",
11
-      "react-native",
12
-      "prop-types",
13
-      "react-test-renderer",
14
-      "jest"
15
-    ]
8
+    "jsx": "react-native"
16 9
   },
17 10
   "include": [
18 11
     "./lib/src/**/*"