@tanstack/react-router 1.0.7 → 1.0.8
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/build/cjs/RouterProvider.js.map +1 -1
- package/build/cjs/link.js +1 -4
- package/build/cjs/link.js.map +1 -1
- package/build/cjs/useNavigate.js.map +1 -1
- package/build/cjs/utils.js +2 -0
- package/build/cjs/utils.js.map +1 -1
- package/build/esm/index.js +3 -4
- package/build/esm/index.js.map +1 -1
- package/build/stats-html.html +1 -1
- package/build/stats-react.json +355 -355
- package/build/types/RouterProvider.d.ts +1 -1
- package/build/types/link.d.ts +21 -24
- package/build/types/useNavigate.d.ts +6 -6
- package/build/types/utils.d.ts +1 -0
- package/build/umd/index.development.js +3 -4
- package/build/umd/index.development.js.map +1 -1
- package/build/umd/index.production.js +1 -1
- package/build/umd/index.production.js.map +1 -1
- package/package.json +2 -2
- package/src/RouterProvider.tsx +4 -4
- package/src/link.tsx +67 -89
- package/src/useNavigate.tsx +21 -22
- package/src/utils.ts +3 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/react-router",
|
|
3
3
|
"author": "Tanner Linsley",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.8",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": "tanstack/router",
|
|
7
7
|
"homepage": "https://tanstack.com/router",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"@tanstack/store": "^0.1.3",
|
|
45
45
|
"tiny-invariant": "^1.3.1",
|
|
46
46
|
"tiny-warning": "^1.0.3",
|
|
47
|
-
"@tanstack/history": "1.0.
|
|
47
|
+
"@tanstack/history": "1.0.8"
|
|
48
48
|
},
|
|
49
49
|
"scripts": {
|
|
50
50
|
"build": "rollup --config rollup.config.js"
|
package/src/RouterProvider.tsx
CHANGED
|
@@ -40,10 +40,10 @@ export interface MatchLocation {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
export type NavigateFn<TRouteTree extends AnyRoute> = <
|
|
43
|
-
TFrom extends RoutePaths<TRouteTree> =
|
|
44
|
-
TTo extends string =
|
|
45
|
-
TMaskFrom extends RoutePaths<TRouteTree> = TFrom,
|
|
46
|
-
TMaskTo extends string =
|
|
43
|
+
TFrom extends RoutePaths<TRouteTree> | string = string,
|
|
44
|
+
TTo extends string | undefined = undefined,
|
|
45
|
+
TMaskFrom extends RoutePaths<TRouteTree> | string = TFrom,
|
|
46
|
+
TMaskTo extends string | undefined = undefined,
|
|
47
47
|
>(
|
|
48
48
|
opts: NavigateOptions<TRouteTree, TFrom, TTo, TMaskFrom, TMaskTo>,
|
|
49
49
|
) => Promise<void>
|
package/src/link.tsx
CHANGED
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
PickRequired,
|
|
20
20
|
UnionToIntersection,
|
|
21
21
|
Updater,
|
|
22
|
+
WithoutEmpty,
|
|
22
23
|
deepEqual,
|
|
23
24
|
functionalUpdate,
|
|
24
25
|
} from './utils'
|
|
@@ -116,10 +117,10 @@ export type RelativeToPathAutoComplete<
|
|
|
116
117
|
|
|
117
118
|
export type NavigateOptions<
|
|
118
119
|
TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
|
|
119
|
-
TFrom extends RoutePaths<TRouteTree> =
|
|
120
|
-
TTo extends string =
|
|
121
|
-
TMaskFrom extends RoutePaths<TRouteTree> = TFrom,
|
|
122
|
-
TMaskTo extends string =
|
|
120
|
+
TFrom extends RoutePaths<TRouteTree> | string = string,
|
|
121
|
+
TTo extends string | undefined = undefined,
|
|
122
|
+
TMaskFrom extends RoutePaths<TRouteTree> | string = TFrom,
|
|
123
|
+
TMaskTo extends string | undefined = undefined,
|
|
123
124
|
> = ToOptions<TRouteTree, TFrom, TTo, TMaskFrom, TMaskTo> & {
|
|
124
125
|
// `replace` is a boolean that determines whether the navigation should replace the current history entry or push a new one.
|
|
125
126
|
replace?: boolean
|
|
@@ -130,26 +131,26 @@ export type NavigateOptions<
|
|
|
130
131
|
|
|
131
132
|
export type ToOptions<
|
|
132
133
|
TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
|
|
133
|
-
TFrom extends RoutePaths<TRouteTree> =
|
|
134
|
-
TTo extends string =
|
|
135
|
-
TMaskFrom extends RoutePaths<TRouteTree> =
|
|
136
|
-
TMaskTo extends string =
|
|
134
|
+
TFrom extends RoutePaths<TRouteTree> | string = string,
|
|
135
|
+
TTo extends string | undefined = undefined,
|
|
136
|
+
TMaskFrom extends RoutePaths<TRouteTree> | string = TFrom,
|
|
137
|
+
TMaskTo extends string | undefined = undefined,
|
|
137
138
|
> = ToSubOptions<TRouteTree, TFrom, TTo> & {
|
|
138
139
|
mask?: ToMaskOptions<TRouteTree, TMaskFrom, TMaskTo>
|
|
139
140
|
}
|
|
140
141
|
|
|
141
142
|
export type ToMaskOptions<
|
|
142
143
|
TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
|
|
143
|
-
TMaskFrom extends RoutePaths<TRouteTree> =
|
|
144
|
-
TMaskTo extends string =
|
|
144
|
+
TMaskFrom extends RoutePaths<TRouteTree> | string = string,
|
|
145
|
+
TMaskTo extends string | undefined = undefined,
|
|
145
146
|
> = ToSubOptions<TRouteTree, TMaskFrom, TMaskTo> & {
|
|
146
147
|
unmaskOnReload?: boolean
|
|
147
148
|
}
|
|
148
149
|
|
|
149
150
|
export type ToSubOptions<
|
|
150
151
|
TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
|
|
151
|
-
TFrom extends RoutePaths<TRouteTree> =
|
|
152
|
-
TTo extends string =
|
|
152
|
+
TFrom extends RoutePaths<TRouteTree> | string = string,
|
|
153
|
+
TTo extends string | undefined = undefined,
|
|
153
154
|
TResolved = ResolveRelativePath<TFrom, NoInfer<TTo>>,
|
|
154
155
|
> = {
|
|
155
156
|
to?: ToPathOption<TRouteTree, TFrom, TTo>
|
|
@@ -162,72 +163,56 @@ export type ToSubOptions<
|
|
|
162
163
|
// // When using relative route paths, this option forces resolution from the current path, instead of the route API's path or `from` path
|
|
163
164
|
} & CheckPath<TRouteTree, NoInfer<TResolved>, {}> &
|
|
164
165
|
SearchParamOptions<TRouteTree, TFrom, TTo, TResolved> &
|
|
165
|
-
PathParamOptions<TRouteTree, TFrom, TResolved>
|
|
166
|
+
PathParamOptions<TRouteTree, TFrom, TTo, TResolved>
|
|
166
167
|
|
|
167
|
-
|
|
168
|
+
type ParamsReducer<TFrom, TTo> = TTo | ((current: TFrom) => TTo)
|
|
169
|
+
|
|
170
|
+
export type ParamOptions<
|
|
168
171
|
TRouteTree extends AnyRoute,
|
|
169
172
|
TFrom,
|
|
170
173
|
TTo,
|
|
171
|
-
TResolved
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
>,
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
:
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
: SearchReducer<TFromSearch, TToSearch>
|
|
195
|
-
}
|
|
174
|
+
TResolved,
|
|
175
|
+
TParamVariant extends 'allParams' | 'fullSearchSchema',
|
|
176
|
+
TFromParams = Expand<RouteByPath<TRouteTree, TFrom>['types'][TParamVariant]>,
|
|
177
|
+
TToParams = TTo extends undefined
|
|
178
|
+
? TFromParams
|
|
179
|
+
: never extends TResolved
|
|
180
|
+
? Expand<RouteByPath<TRouteTree, TTo>['types'][TParamVariant]>
|
|
181
|
+
: Expand<RouteByPath<TRouteTree, TResolved>['types'][TParamVariant]>,
|
|
182
|
+
TReducer = ParamsReducer<TFromParams, TToParams>,
|
|
183
|
+
> = Expand<WithoutEmpty<PickRequired<TToParams>>> extends never
|
|
184
|
+
? Partial<MakeParamOption<TParamVariant, true | TReducer>>
|
|
185
|
+
: TFromParams extends Expand<WithoutEmpty<PickRequired<TToParams>>>
|
|
186
|
+
? MakeParamOption<TParamVariant, true | TReducer>
|
|
187
|
+
: MakeParamOption<TParamVariant, TReducer>
|
|
188
|
+
|
|
189
|
+
type MakeParamOption<
|
|
190
|
+
TParamVariant extends 'allParams' | 'fullSearchSchema',
|
|
191
|
+
T,
|
|
192
|
+
> = TParamVariant extends 'allParams'
|
|
193
|
+
? MakePathParamOptions<T>
|
|
194
|
+
: MakeSearchParamOptions<T>
|
|
195
|
+
type MakeSearchParamOptions<T> = { search: T }
|
|
196
|
+
type MakePathParamOptions<T> = { params: T }
|
|
196
197
|
|
|
197
|
-
type
|
|
198
|
+
export type SearchParamOptions<
|
|
199
|
+
TRouteTree extends AnyRoute,
|
|
200
|
+
TFrom,
|
|
201
|
+
TTo,
|
|
202
|
+
TResolved,
|
|
203
|
+
> = ParamOptions<TRouteTree, TFrom, TTo, TResolved, 'fullSearchSchema'>
|
|
198
204
|
|
|
199
205
|
export type PathParamOptions<
|
|
200
206
|
TRouteTree extends AnyRoute,
|
|
201
207
|
TFrom,
|
|
202
208
|
TTo,
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
PickRequired<RouteByPath<TRouteTree, TFrom>['types']['allParams']>
|
|
206
|
-
>
|
|
207
|
-
>,
|
|
208
|
-
TFromParamsOptional = Omit<AllParams<TRouteTree>, keyof TFromParamsEnsured>,
|
|
209
|
-
TFromParams = Expand<TFromParamsOptional & TFromParamsEnsured>,
|
|
210
|
-
TToParams = Expand<RouteByPath<TRouteTree, TTo>['types']['allParams']>,
|
|
211
|
-
> = never extends TToParams
|
|
212
|
-
? {
|
|
213
|
-
params?: true | ParamsReducer<Partial<TFromParams>, Partial<TFromParams>>
|
|
214
|
-
}
|
|
215
|
-
: keyof PickRequired<TToParams> extends never
|
|
216
|
-
? {
|
|
217
|
-
params?: true | ParamsReducer<TFromParams, TToParams>
|
|
218
|
-
}
|
|
219
|
-
: {
|
|
220
|
-
params: TFromParamsEnsured extends PickRequired<TToParams>
|
|
221
|
-
? true | ParamsReducer<TFromParams, TToParams>
|
|
222
|
-
: ParamsReducer<TFromParams, TToParams>
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
type ParamsReducer<TFrom, TTo> = TTo | ((current: TFrom) => TTo)
|
|
209
|
+
TResolved,
|
|
210
|
+
> = ParamOptions<TRouteTree, TFrom, TTo, TResolved, 'allParams'>
|
|
226
211
|
|
|
227
212
|
export type ToPathOption<
|
|
228
213
|
TRouteTree extends AnyRoute = AnyRoute,
|
|
229
|
-
TFrom extends RoutePaths<TRouteTree> =
|
|
230
|
-
TTo extends string =
|
|
214
|
+
TFrom extends RoutePaths<TRouteTree> | string = string,
|
|
215
|
+
TTo extends string | undefined = undefined,
|
|
231
216
|
> =
|
|
232
217
|
| TTo
|
|
233
218
|
| RelativeToPathAutoComplete<
|
|
@@ -238,8 +223,8 @@ export type ToPathOption<
|
|
|
238
223
|
|
|
239
224
|
export type ToIdOption<
|
|
240
225
|
TRouteTree extends AnyRoute = AnyRoute,
|
|
241
|
-
TFrom extends RoutePaths<TRouteTree> =
|
|
242
|
-
TTo extends string =
|
|
226
|
+
TFrom extends RoutePaths<TRouteTree> | undefined = undefined,
|
|
227
|
+
TTo extends string | undefined = undefined,
|
|
243
228
|
> =
|
|
244
229
|
| TTo
|
|
245
230
|
| RelativeToPathAutoComplete<
|
|
@@ -256,10 +241,10 @@ export interface ActiveOptions {
|
|
|
256
241
|
|
|
257
242
|
export type LinkOptions<
|
|
258
243
|
TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
|
|
259
|
-
TFrom extends RoutePaths<TRouteTree> =
|
|
260
|
-
TTo extends string =
|
|
261
|
-
TMaskFrom extends RoutePaths<TRouteTree> = TFrom,
|
|
262
|
-
TMaskTo extends string =
|
|
244
|
+
TFrom extends RoutePaths<TRouteTree> | string = string,
|
|
245
|
+
TTo extends string | undefined = undefined,
|
|
246
|
+
TMaskFrom extends RoutePaths<TRouteTree> | string = TFrom,
|
|
247
|
+
TMaskTo extends string | undefined = undefined,
|
|
263
248
|
> = NavigateOptions<TRouteTree, TFrom, TTo, TMaskFrom, TMaskTo> & {
|
|
264
249
|
// The standard anchor tag target attribute
|
|
265
250
|
target?: HTMLAnchorElement['target']
|
|
@@ -348,20 +333,13 @@ const preloadWarning = 'Error preloading route! ☝️'
|
|
|
348
333
|
|
|
349
334
|
export function useLinkProps<
|
|
350
335
|
TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
|
|
351
|
-
TFrom extends RoutePaths<TRouteTree> =
|
|
352
|
-
TTo extends string =
|
|
353
|
-
TMaskFrom extends RoutePaths<TRouteTree> =
|
|
354
|
-
TMaskTo extends string =
|
|
355
|
-
>(
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
}: UseLinkPropsOptions<
|
|
359
|
-
TRouteTree,
|
|
360
|
-
TFrom,
|
|
361
|
-
TTo,
|
|
362
|
-
TMaskFrom,
|
|
363
|
-
TMaskTo
|
|
364
|
-
>): React.AnchorHTMLAttributes<HTMLAnchorElement> {
|
|
336
|
+
TFrom extends RoutePaths<TRouteTree> | string = string,
|
|
337
|
+
TTo extends string | undefined = undefined,
|
|
338
|
+
TMaskFrom extends RoutePaths<TRouteTree> | string = TFrom,
|
|
339
|
+
TMaskTo extends string | undefined = undefined,
|
|
340
|
+
>(
|
|
341
|
+
options: UseLinkPropsOptions<TRouteTree, TFrom, TTo, TMaskFrom, TMaskTo>,
|
|
342
|
+
): React.AnchorHTMLAttributes<HTMLAnchorElement> {
|
|
365
343
|
const router = useRouter()
|
|
366
344
|
const matchPathname = useMatch({
|
|
367
345
|
strict: false,
|
|
@@ -574,10 +552,10 @@ export function useLinkProps<
|
|
|
574
552
|
export interface LinkComponent<TProps extends Record<string, any> = {}> {
|
|
575
553
|
<
|
|
576
554
|
TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
|
|
577
|
-
TFrom extends RoutePaths<TRouteTree> =
|
|
578
|
-
TTo extends string =
|
|
579
|
-
TMaskFrom extends RoutePaths<TRouteTree> =
|
|
580
|
-
TMaskTo extends string =
|
|
555
|
+
TFrom extends RoutePaths<TRouteTree> | string = string,
|
|
556
|
+
TTo extends string | undefined = undefined,
|
|
557
|
+
TMaskFrom extends RoutePaths<TRouteTree> | string = TFrom,
|
|
558
|
+
TMaskTo extends string | undefined = undefined,
|
|
581
559
|
>(
|
|
582
560
|
props: LinkProps<TRouteTree, TFrom, TTo, TMaskFrom, TMaskTo> &
|
|
583
561
|
TProps &
|
package/src/useNavigate.tsx
CHANGED
|
@@ -5,11 +5,10 @@ import { LinkOptions, NavigateOptions } from './link'
|
|
|
5
5
|
import { AnyRoute } from './route'
|
|
6
6
|
import { RoutePaths } from './routeInfo'
|
|
7
7
|
import { RegisteredRouter } from './router'
|
|
8
|
-
import { useLayoutEffect } from './utils'
|
|
9
8
|
|
|
10
9
|
export function useNavigate<
|
|
11
10
|
TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
|
|
12
|
-
TDefaultFrom extends RoutePaths<TRouteTree> =
|
|
11
|
+
TDefaultFrom extends RoutePaths<TRouteTree> | string = string,
|
|
13
12
|
>(_defaultOpts?: { from?: TDefaultFrom }) {
|
|
14
13
|
const { navigate, buildLocation } = useRouter()
|
|
15
14
|
|
|
@@ -20,10 +19,10 @@ export function useNavigate<
|
|
|
20
19
|
|
|
21
20
|
return React.useCallback(
|
|
22
21
|
<
|
|
23
|
-
TFrom extends RoutePaths<TRouteTree> = TDefaultFrom,
|
|
24
|
-
TTo extends string =
|
|
25
|
-
TMaskFrom extends RoutePaths<TRouteTree
|
|
26
|
-
TMaskTo extends string =
|
|
22
|
+
TFrom extends RoutePaths<TRouteTree> | string = TDefaultFrom,
|
|
23
|
+
TTo extends string | undefined = undefined,
|
|
24
|
+
TMaskFrom extends RoutePaths<TRouteTree>| string = TFrom,
|
|
25
|
+
TMaskTo extends string | undefined = undefined,
|
|
27
26
|
>({
|
|
28
27
|
from,
|
|
29
28
|
...rest
|
|
@@ -54,10 +53,10 @@ export function useNavigate<
|
|
|
54
53
|
|
|
55
54
|
export function Navigate<
|
|
56
55
|
TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
|
|
57
|
-
TFrom extends RoutePaths<TRouteTree> =
|
|
58
|
-
TTo extends string =
|
|
59
|
-
TMaskFrom extends RoutePaths<TRouteTree> =
|
|
60
|
-
TMaskTo extends string =
|
|
56
|
+
TFrom extends RoutePaths<TRouteTree> | string = string,
|
|
57
|
+
TTo extends string | undefined = undefined,
|
|
58
|
+
TMaskFrom extends RoutePaths<TRouteTree> | string = TFrom,
|
|
59
|
+
TMaskTo extends string | undefined = undefined,
|
|
61
60
|
>(props: NavigateOptions<TRouteTree, TFrom, TTo, TMaskFrom, TMaskTo>): null {
|
|
62
61
|
const { navigate } = useRouter()
|
|
63
62
|
const match = useMatch({ strict: false })
|
|
@@ -74,19 +73,19 @@ export function Navigate<
|
|
|
74
73
|
|
|
75
74
|
export type UseLinkPropsOptions<
|
|
76
75
|
TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
|
|
77
|
-
TFrom extends RoutePaths<TRouteTree> =
|
|
78
|
-
TTo extends string =
|
|
79
|
-
TMaskFrom extends RoutePaths<TRouteTree> =
|
|
80
|
-
TMaskTo extends string =
|
|
76
|
+
TFrom extends RoutePaths<TRouteTree> | string = string,
|
|
77
|
+
TTo extends string | undefined= undefined,
|
|
78
|
+
TMaskFrom extends RoutePaths<TRouteTree> | string = TFrom,
|
|
79
|
+
TMaskTo extends string | undefined = undefined,
|
|
81
80
|
> = ActiveLinkOptions<TRouteTree, TFrom, TTo, TMaskFrom, TMaskTo> &
|
|
82
81
|
React.AnchorHTMLAttributes<HTMLAnchorElement>
|
|
83
82
|
|
|
84
83
|
export type LinkProps<
|
|
85
84
|
TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
|
|
86
|
-
TFrom extends RoutePaths<TRouteTree> =
|
|
87
|
-
TTo extends string =
|
|
88
|
-
TMaskFrom extends RoutePaths<TRouteTree> =
|
|
89
|
-
TMaskTo extends string =
|
|
85
|
+
TFrom extends RoutePaths<TRouteTree> | string = string,
|
|
86
|
+
TTo extends string| undefined = undefined,
|
|
87
|
+
TMaskFrom extends RoutePaths<TRouteTree> | string = TFrom,
|
|
88
|
+
TMaskTo extends string | undefined = undefined,
|
|
90
89
|
> = ActiveLinkOptions<TRouteTree, TFrom, TTo, TMaskFrom, TMaskTo> &
|
|
91
90
|
Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, 'children'> & {
|
|
92
91
|
// If a function is passed as a child, it will be given the `isActive` boolean to aid in further styling on the element it returns
|
|
@@ -97,10 +96,10 @@ export type LinkProps<
|
|
|
97
96
|
|
|
98
97
|
export type ActiveLinkOptions<
|
|
99
98
|
TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
|
|
100
|
-
TFrom extends RoutePaths<TRouteTree> =
|
|
101
|
-
TTo extends string =
|
|
102
|
-
TMaskFrom extends RoutePaths<TRouteTree> =
|
|
103
|
-
TMaskTo extends string =
|
|
99
|
+
TFrom extends RoutePaths<TRouteTree> | string = string,
|
|
100
|
+
TTo extends string | undefined = undefined,
|
|
101
|
+
TMaskFrom extends RoutePaths<TRouteTree> | string = TFrom,
|
|
102
|
+
TMaskTo extends string | undefined = undefined,
|
|
104
103
|
> = LinkOptions<TRouteTree, TFrom, TTo, TMaskFrom, TMaskTo> & {
|
|
105
104
|
// A function that returns additional props for the `active` state of this link. These props override other props passed to the link (`style`'s are merged, `className`'s are concatenated)
|
|
106
105
|
activeProps?:
|
package/src/utils.ts
CHANGED
|
@@ -26,6 +26,9 @@ export type PickRequired<T> = {
|
|
|
26
26
|
[K in keyof T as undefined extends T[K] ? never : K]: T[K]
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
// from https://stackoverflow.com/a/76458160
|
|
30
|
+
export type WithoutEmpty<T> = T extends T ? ({} extends T ? never : T) : never
|
|
31
|
+
|
|
29
32
|
// export type Expand<T> = T
|
|
30
33
|
export type Expand<T> = T extends object
|
|
31
34
|
? T extends infer O
|