@granite-js/react-native 0.1.32 → 0.1.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # @granite-js/react-native
2
2
 
3
+ ## 0.1.33
4
+
5
+ ### Patch Changes
6
+
7
+ - fdf55a6: fix(router): type infer incorrect undefined
8
+ - Updated dependencies [fdf55a6]
9
+ - @granite-js/native@0.1.33
10
+ - @granite-js/image@0.1.33
11
+ - @granite-js/jest@0.1.33
12
+ - @granite-js/lottie@0.1.33
13
+ - @granite-js/style-utils@0.1.33
14
+ - @granite-js/cli@0.1.33
15
+ - @granite-js/mpack@0.1.33
16
+ - @granite-js/plugin-core@0.1.33
17
+
3
18
  ## 0.1.32
4
19
 
5
20
  ### Patch Changes
@@ -48,13 +48,13 @@ export declare function createRoute<TSchema extends StandardSchemaV1<any, any>>(
48
48
  _path: keyof RegisterScreenInput;
49
49
  useNavigation: typeof useNavigation;
50
50
  useParams: () => InferOutput<TSchema>;
51
- _inputType?: InferInput<TSchema>;
52
- _outputType?: InferOutput<TSchema>;
51
+ _inputType: InferInput<TSchema>;
52
+ _outputType: InferOutput<TSchema>;
53
53
  };
54
54
  export declare function createRoute<T extends Readonly<object | undefined>>(path: keyof RegisterScreenInput, options: RouteOptions<T>): {
55
55
  _path: keyof RegisterScreenInput;
56
56
  useNavigation: typeof useNavigation;
57
57
  useParams: () => T;
58
- _inputType?: T;
59
- _outputType?: T;
58
+ _inputType: T;
59
+ _outputType: T;
60
60
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@granite-js/react-native",
3
- "version": "0.1.32",
3
+ "version": "0.1.33",
4
4
  "description": "The Granite Framework",
5
5
  "bin": {
6
6
  "granite": "./bin/cli.js"
@@ -91,7 +91,7 @@
91
91
  "@babel/core": "7.28.5",
92
92
  "@babel/preset-env": "7.28.5",
93
93
  "@babel/preset-typescript": "7.28.5",
94
- "@granite-js/native": "0.1.32",
94
+ "@granite-js/native": "0.1.33",
95
95
  "@testing-library/dom": "^10.4.0",
96
96
  "@testing-library/react": "^16.1.0",
97
97
  "@types/babel__core": "^7",
@@ -118,13 +118,13 @@
118
118
  "react-native": "*"
119
119
  },
120
120
  "dependencies": {
121
- "@granite-js/cli": "0.1.32",
122
- "@granite-js/image": "0.1.32",
123
- "@granite-js/jest": "0.1.32",
124
- "@granite-js/lottie": "0.1.32",
125
- "@granite-js/mpack": "0.1.32",
126
- "@granite-js/plugin-core": "0.1.32",
127
- "@granite-js/style-utils": "0.1.32",
121
+ "@granite-js/cli": "0.1.33",
122
+ "@granite-js/image": "0.1.33",
123
+ "@granite-js/jest": "0.1.33",
124
+ "@granite-js/lottie": "0.1.33",
125
+ "@granite-js/mpack": "0.1.33",
126
+ "@granite-js/plugin-core": "0.1.33",
127
+ "@granite-js/style-utils": "0.1.33",
128
128
  "@standard-schema/spec": "^1.0.0",
129
129
  "es-toolkit": "^1.39.8",
130
130
  "react-native-url-polyfill": "3.0.0"
@@ -77,6 +77,30 @@ describe('createRoute', () => {
77
77
  // @ts-expect-error Type error should occur since 'from' and 'strict: false' are conflicting options
78
78
  assertType(useParams({ from: '/test', strict: false }));
79
79
  });
80
+
81
+ it('should infer _inputType and _outputType without undefined for function pattern', () => {
82
+ type InputType = (typeof Route)['_inputType'];
83
+ type OutputType = (typeof Route)['_outputType'];
84
+
85
+ // _inputType should be inferred as the exact type, not a union with undefined
86
+ assertType<{
87
+ id: string;
88
+ name: string;
89
+ }>({} as InputType);
90
+
91
+ // _outputType should be inferred as the exact type, not a union with undefined
92
+ assertType<{
93
+ id: string;
94
+ name: string;
95
+ }>({} as OutputType);
96
+
97
+ // Verify that undefined is not part of the union
98
+ type InputHasUndefined = undefined extends InputType ? true : false;
99
+ type OutputHasUndefined = undefined extends OutputType ? true : false;
100
+
101
+ assertType<false>({} as InputHasUndefined);
102
+ assertType<false>({} as OutputHasUndefined);
103
+ });
80
104
  });
81
105
 
82
106
  describe('createRoute with StandardSchema', () => {
@@ -95,7 +119,56 @@ describe('createRoute with StandardSchema', () => {
95
119
  }>(RouteWithSchema.useParams());
96
120
  });
97
121
 
122
+ it('should infer _inputType and _outputType without undefined', () => {
123
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
124
+ const RouteWithSchema = createRoute('/test-schema', {
125
+ component: () => null,
126
+ validateParams: z.object({
127
+ id: z.string(),
128
+ count: z.number(),
129
+ }),
130
+ });
131
+
132
+ type InputType = (typeof RouteWithSchema)['_inputType'];
133
+ type OutputType = (typeof RouteWithSchema)['_outputType'];
134
+ type UseParamsReturnType = ReturnType<(typeof RouteWithSchema)['useParams']>;
135
+
136
+ // _inputType should be inferred as the exact type, not a union with undefined
137
+ assertType<{
138
+ id: string;
139
+ count: number;
140
+ }>({} as InputType);
141
+
142
+ // _outputType should be inferred as the exact type, not a union with undefined
143
+ assertType<{
144
+ id: string;
145
+ count: number;
146
+ }>({} as OutputType);
147
+
148
+ // useParams should return the exact type, not a union with undefined
149
+ assertType<{
150
+ id: string;
151
+ count: number;
152
+ }>({} as UseParamsReturnType);
153
+
154
+ // Verify that undefined is not part of the union for all types
155
+ type InputHasUndefined = undefined extends InputType ? true : false;
156
+ type OutputHasUndefined = undefined extends OutputType ? true : false;
157
+ type UseParamsHasUndefined = undefined extends UseParamsReturnType ? true : false;
158
+
159
+ assertType<false>({} as InputHasUndefined);
160
+ assertType<false>({} as OutputHasUndefined);
161
+ assertType<false>({} as UseParamsHasUndefined);
162
+
163
+ // useNavigation should accept input type for navigate parameters
164
+ const navigation = useNavigation();
165
+
166
+ // Should accept exact input type
167
+ navigation.navigate('/test-schema', { id: 'test', count: 123 });
168
+ });
169
+
98
170
  it('should infer output type from transformation', () => {
171
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
99
172
  const RouteWithTransform = createRoute('/test-transform', {
100
173
  component: () => null,
101
174
  validateParams: z.object({
@@ -103,10 +176,35 @@ describe('createRoute with StandardSchema', () => {
103
176
  }),
104
177
  });
105
178
 
106
- // Should be number (output), not string (input)
179
+ type InputType = (typeof RouteWithTransform)['_inputType'];
180
+ type OutputType = (typeof RouteWithTransform)['_outputType'];
181
+ type UseParamsReturnType = ReturnType<(typeof RouteWithTransform)['useParams']>;
182
+
183
+ // _inputType should be string (before transformation)
184
+ assertType<{
185
+ id: string;
186
+ }>({} as InputType);
187
+
188
+ // _outputType should be number (after transformation)
189
+ assertType<{
190
+ id: number;
191
+ }>({} as OutputType);
192
+
193
+ // useParams should return output type (number)
107
194
  assertType<{
108
195
  id: number;
109
- }>(RouteWithTransform.useParams());
196
+ }>({} as UseParamsReturnType);
197
+
198
+ // useNavigation should accept input type (string)
199
+ const navigation = useNavigation();
200
+ navigation.navigate('/test-transform', { id: 'test-id' });
201
+
202
+ // Verify that input and output types are different
203
+ type InputIsString = InputType extends { id: string } ? true : false;
204
+ type OutputIsNumber = OutputType extends { id: number } ? true : false;
205
+
206
+ assertType<true>({} as InputIsString);
207
+ assertType<true>({} as OutputIsNumber);
110
208
  });
111
209
 
112
210
  it('should work with useParams hook', () => {
@@ -175,8 +175,8 @@ export function createRoute<TSchema extends StandardSchemaV1<any, any>>(
175
175
  _path: keyof RegisterScreenInput;
176
176
  useNavigation: typeof useNavigation;
177
177
  useParams: () => InferOutput<TSchema>;
178
- _inputType?: InferInput<TSchema>;
179
- _outputType?: InferOutput<TSchema>;
178
+ _inputType: InferInput<TSchema>;
179
+ _outputType: InferOutput<TSchema>;
180
180
  };
181
181
 
182
182
  // Overload 2: Function pattern
@@ -187,8 +187,8 @@ export function createRoute<T extends Readonly<object | undefined>>(
187
187
  _path: keyof RegisterScreenInput;
188
188
  useNavigation: typeof useNavigation;
189
189
  useParams: () => T;
190
- _inputType?: T;
191
- _outputType?: T;
190
+ _inputType: T;
191
+ _outputType: T;
192
192
  };
193
193
 
194
194
  // Implementation
@@ -205,5 +205,10 @@ export function createRoute(path: keyof RegisterScreenInput, options: RouteOptio
205
205
  _path,
206
206
  useNavigation,
207
207
  useParams: () => useParams({ from: _path as keyof RegisterScreen, strict: true }),
208
+
209
+ // These properties are only used for type inference in the generated router files
210
+ // The actual values are never accessed at runtime
211
+ _inputType: {},
212
+ _outputType: {},
208
213
  };
209
214
  }