@tanstack/table-core 8.2.4 → 8.3.0
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/columnHelper.js +62 -0
- package/build/cjs/columnHelper.js.map +1 -0
- package/build/cjs/core/cell.js.map +1 -1
- package/build/cjs/core/column.js +17 -3
- package/build/cjs/core/column.js.map +1 -1
- package/build/cjs/core/headers.js.map +1 -1
- package/build/cjs/core/table.js.map +1 -1
- package/build/cjs/features/Expanding.js +1 -1
- package/build/cjs/features/Expanding.js.map +1 -1
- package/build/cjs/features/Filters.js +1 -1
- package/build/cjs/features/Filters.js.map +1 -1
- package/build/cjs/index.js +2 -0
- package/build/cjs/index.js.map +1 -1
- package/build/cjs/utils.js +3 -0
- package/build/cjs/utils.js.map +1 -1
- package/build/esm/index.js +69 -6
- package/build/esm/index.js.map +1 -1
- package/build/stats-html.html +1451 -106
- package/build/stats-react.json +333 -308
- package/build/types/index.d.ts +52 -32
- package/build/umd/index.development.js +69 -5
- 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 +1 -1
- package/src/columnHelper.ts +74 -0
- package/src/core/cell.ts +17 -10
- package/src/core/column.ts +43 -34
- package/src/core/headers.ts +8 -6
- package/src/core/table.ts +9 -7
- package/src/features/Expanding.ts +5 -3
- package/src/features/Filters.ts +1 -1
- package/src/index.ts +1 -0
- package/src/utils.ts +51 -1
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/table-core",
|
|
3
3
|
"author": "Tanner Linsley",
|
|
4
|
-
"version": "8.
|
|
4
|
+
"version": "8.3.0",
|
|
5
5
|
"description": "Headless UI for building powerful tables & datagrids for TS/JS.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"homepage": "https://github.com/tanstack/table#readme",
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { AccessorFn, ColumnDef, RowData } from './types'
|
|
2
|
+
import { DeepKeys, DeepValue } from './utils'
|
|
3
|
+
|
|
4
|
+
// type Person = {
|
|
5
|
+
// firstName: string
|
|
6
|
+
// lastName: string
|
|
7
|
+
// age: number
|
|
8
|
+
// visits: number
|
|
9
|
+
// status: string
|
|
10
|
+
// progress: number
|
|
11
|
+
// nested: {
|
|
12
|
+
// foo: [
|
|
13
|
+
// {
|
|
14
|
+
// bar: 'bar'
|
|
15
|
+
// }
|
|
16
|
+
// ]
|
|
17
|
+
// bar: { subBar: boolean }[]
|
|
18
|
+
// baz: {
|
|
19
|
+
// foo: 'foo'
|
|
20
|
+
// bar: {
|
|
21
|
+
// baz: 'baz'
|
|
22
|
+
// }
|
|
23
|
+
// }
|
|
24
|
+
// }
|
|
25
|
+
// }
|
|
26
|
+
|
|
27
|
+
// const test: DeepKeys<Person> = 'nested.foo.0.bar'
|
|
28
|
+
// const test2: DeepKeys<Person> = 'nested.bar'
|
|
29
|
+
|
|
30
|
+
// const helper = createColumnHelper<Person>()
|
|
31
|
+
|
|
32
|
+
// helper.accessor('nested.foo', {
|
|
33
|
+
// cell: info => info.getValue(),
|
|
34
|
+
// })
|
|
35
|
+
|
|
36
|
+
// helper.accessor('nested.foo.0.bar', {
|
|
37
|
+
// cell: info => info.getValue(),
|
|
38
|
+
// })
|
|
39
|
+
|
|
40
|
+
// helper.accessor('nested.bar', {
|
|
41
|
+
// cell: info => info.getValue(),
|
|
42
|
+
// })
|
|
43
|
+
|
|
44
|
+
export type ColumnHelper<TData extends RowData> = {
|
|
45
|
+
accessor: <
|
|
46
|
+
TAccessor extends AccessorFn<TData> | DeepKeys<TData>,
|
|
47
|
+
TValue extends TAccessor extends AccessorFn<TData, infer TReturn>
|
|
48
|
+
? TReturn
|
|
49
|
+
: TAccessor extends DeepKeys<TData>
|
|
50
|
+
? DeepValue<TData, TAccessor>
|
|
51
|
+
: never
|
|
52
|
+
>(
|
|
53
|
+
accessor: TAccessor,
|
|
54
|
+
column: Omit<ColumnDef<TData, TValue>, 'accessorKey'>
|
|
55
|
+
) => ColumnDef<TData, TValue>
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function createColumnHelper<
|
|
59
|
+
TData extends RowData
|
|
60
|
+
>(): ColumnHelper<TData> {
|
|
61
|
+
return {
|
|
62
|
+
accessor: (accessor, column) => {
|
|
63
|
+
return typeof accessor === 'function'
|
|
64
|
+
? ({
|
|
65
|
+
...column,
|
|
66
|
+
accessorFn: accessor,
|
|
67
|
+
} as any)
|
|
68
|
+
: {
|
|
69
|
+
...column,
|
|
70
|
+
accessorKey: accessor,
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
}
|
|
74
|
+
}
|
package/src/core/cell.ts
CHANGED
|
@@ -1,19 +1,26 @@
|
|
|
1
1
|
import { RowData, Cell, Column, Row, Table } from '../types'
|
|
2
|
+
import { IsAny, IsKnown } from '../utils'
|
|
3
|
+
|
|
4
|
+
type NoInfer<T> = [T][T extends any ? 0 : never]
|
|
5
|
+
|
|
6
|
+
type Getter<TValue> = <TTValue = TValue>() => NoInfer<TTValue>
|
|
7
|
+
|
|
8
|
+
export type CellContext<TData extends RowData, TValue> = {
|
|
9
|
+
table: Table<TData>
|
|
10
|
+
column: Column<TData, TValue>
|
|
11
|
+
row: Row<TData>
|
|
12
|
+
cell: Cell<TData, TValue>
|
|
13
|
+
getValue: Getter<TValue>
|
|
14
|
+
renderValue: Getter<TValue | null>
|
|
15
|
+
}
|
|
2
16
|
|
|
3
17
|
export type CoreCell<TData extends RowData, TValue> = {
|
|
4
18
|
id: string
|
|
5
|
-
getValue: <
|
|
6
|
-
renderValue: <
|
|
19
|
+
getValue: CellContext<TData, TValue>['getValue']
|
|
20
|
+
renderValue: CellContext<TData, TValue>['renderValue']
|
|
7
21
|
row: Row<TData>
|
|
8
22
|
column: Column<TData, TValue>
|
|
9
|
-
getContext: () =>
|
|
10
|
-
table: Table<TData>
|
|
11
|
-
column: Column<TData, TValue>
|
|
12
|
-
row: Row<TData>
|
|
13
|
-
cell: Cell<TData, TValue>
|
|
14
|
-
getValue: <TTValue = TValue>() => TTValue
|
|
15
|
-
renderValue: <TTValue = TValue>() => TTValue | null
|
|
16
|
-
}
|
|
23
|
+
getContext: () => CellContext<TData, TValue>
|
|
17
24
|
}
|
|
18
25
|
|
|
19
26
|
export function createCell<TData extends RowData, TValue>(
|
package/src/core/column.ts
CHANGED
|
@@ -7,32 +7,26 @@ import {
|
|
|
7
7
|
RowData,
|
|
8
8
|
ColumnMeta,
|
|
9
9
|
} from '../types'
|
|
10
|
-
import { memo, UnionToIntersection } from '../utils'
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
|
|
14
|
-
export type
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
ReturnType<CoreHeader<TData, TValue>['getContext']>
|
|
20
|
-
>
|
|
21
|
-
footer?: ColumnDefTemplate<
|
|
22
|
-
ReturnType<CoreHeader<TData, TValue>['getContext']>
|
|
23
|
-
>
|
|
24
|
-
cell?: ColumnDefTemplate<ReturnType<CoreCell<TData, TValue>['getContext']>>
|
|
10
|
+
import { DeepKeys, IsKnown, memo, UnionToIntersection } from '../utils'
|
|
11
|
+
import { CellContext } from './cell'
|
|
12
|
+
import { HeaderContext } from './headers'
|
|
13
|
+
|
|
14
|
+
export type CoreColumnDefBase<TData extends RowData, TValue> = {
|
|
15
|
+
columns?: ColumnDef<TData, unknown>[]
|
|
16
|
+
header?: ColumnDefTemplate<HeaderContext<TData, TValue>>
|
|
17
|
+
footer?: ColumnDefTemplate<HeaderContext<TData, TValue>>
|
|
18
|
+
cell?: ColumnDefTemplate<CellContext<TData, TValue>>
|
|
25
19
|
meta?: ColumnMeta
|
|
26
20
|
}
|
|
27
21
|
|
|
28
|
-
type CoreColumnDefDisplay<
|
|
29
|
-
TData,
|
|
22
|
+
export type CoreColumnDefDisplay<
|
|
23
|
+
TData extends RowData,
|
|
30
24
|
TValue
|
|
31
|
-
> & {
|
|
25
|
+
> = CoreColumnDefBase<TData, TValue> & {
|
|
32
26
|
id: string
|
|
33
27
|
}
|
|
34
28
|
|
|
35
|
-
type CoreColumnDefDisplayWithStringHeader<
|
|
29
|
+
export type CoreColumnDefDisplayWithStringHeader<
|
|
36
30
|
TData extends RowData,
|
|
37
31
|
TValue
|
|
38
32
|
> = CoreColumnDefBase<TData, TValue> & {
|
|
@@ -40,40 +34,40 @@ type CoreColumnDefDisplayWithStringHeader<
|
|
|
40
34
|
id?: string
|
|
41
35
|
}
|
|
42
36
|
|
|
43
|
-
type CoreColumnDefAccessorFn<
|
|
37
|
+
export type CoreColumnDefAccessorFn<
|
|
44
38
|
TData extends RowData,
|
|
45
|
-
TValue
|
|
39
|
+
TValue
|
|
46
40
|
> = CoreColumnDefBase<TData, TValue> & {
|
|
47
41
|
accessorFn: AccessorFn<TData, TValue>
|
|
48
42
|
id: string
|
|
49
|
-
// accessorKey?: never
|
|
50
43
|
}
|
|
51
44
|
|
|
52
|
-
type CoreColumnDefAccessorKey<
|
|
45
|
+
export type CoreColumnDefAccessorKey<
|
|
53
46
|
TData extends RowData,
|
|
54
47
|
TValue
|
|
55
48
|
> = CoreColumnDefBase<TData, TValue> & {
|
|
56
|
-
accessorKey:
|
|
49
|
+
accessorKey: DeepKeys<TData>
|
|
57
50
|
id?: string
|
|
58
|
-
// accessorFn?: never
|
|
59
51
|
}
|
|
60
52
|
|
|
61
53
|
export type CoreColumnDef<TData extends RowData, TValue> =
|
|
62
54
|
| CoreColumnDefDisplay<TData, TValue>
|
|
63
55
|
| CoreColumnDefDisplayWithStringHeader<TData, TValue>
|
|
64
|
-
| CoreColumnDefAccessorFn<TData>
|
|
56
|
+
| CoreColumnDefAccessorFn<TData, TValue>
|
|
65
57
|
| CoreColumnDefAccessorKey<TData, TValue>
|
|
66
58
|
|
|
67
59
|
export type CoreColumnDefResolved<
|
|
68
60
|
TData extends RowData,
|
|
69
61
|
TValue = unknown
|
|
70
|
-
> = Partial<UnionToIntersection<CoreColumnDef<TData, TValue>>>
|
|
62
|
+
> = Partial<UnionToIntersection<CoreColumnDef<TData, TValue>>> & {
|
|
63
|
+
accessorKey?: string
|
|
64
|
+
}
|
|
71
65
|
|
|
72
66
|
export type CoreColumn<TData extends RowData, TValue> = {
|
|
73
67
|
id: string
|
|
74
68
|
depth: number
|
|
75
69
|
accessorFn?: AccessorFn<TData, TValue>
|
|
76
|
-
columnDef: ColumnDef<TData>
|
|
70
|
+
columnDef: ColumnDef<TData, TValue>
|
|
77
71
|
columns: Column<TData, TValue>[]
|
|
78
72
|
parent?: Column<TData, TValue>
|
|
79
73
|
getFlatColumns: () => Column<TData, TValue>[]
|
|
@@ -82,7 +76,7 @@ export type CoreColumn<TData extends RowData, TValue> = {
|
|
|
82
76
|
|
|
83
77
|
export function createColumn<TData extends RowData, TValue>(
|
|
84
78
|
table: Table<TData>,
|
|
85
|
-
columnDef: ColumnDef<TData>,
|
|
79
|
+
columnDef: ColumnDef<TData, TValue>,
|
|
86
80
|
depth: number,
|
|
87
81
|
parent?: Column<TData, TValue>
|
|
88
82
|
) {
|
|
@@ -93,9 +87,11 @@ export function createColumn<TData extends RowData, TValue>(
|
|
|
93
87
|
...columnDef,
|
|
94
88
|
} as CoreColumnDefResolved<TData>
|
|
95
89
|
|
|
90
|
+
const accessorKey = resolvedColumnDef.accessorKey
|
|
91
|
+
|
|
96
92
|
let id =
|
|
97
93
|
resolvedColumnDef.id ??
|
|
98
|
-
|
|
94
|
+
(accessorKey ? accessorKey.replace('.', '_') : undefined) ??
|
|
99
95
|
(typeof resolvedColumnDef.header === 'string'
|
|
100
96
|
? resolvedColumnDef.header
|
|
101
97
|
: undefined)
|
|
@@ -104,9 +100,22 @@ export function createColumn<TData extends RowData, TValue>(
|
|
|
104
100
|
|
|
105
101
|
if (resolvedColumnDef.accessorFn) {
|
|
106
102
|
accessorFn = resolvedColumnDef.accessorFn
|
|
107
|
-
} else if (
|
|
108
|
-
|
|
109
|
-
|
|
103
|
+
} else if (accessorKey) {
|
|
104
|
+
// Support deep accessor keys
|
|
105
|
+
if (accessorKey.includes('.')) {
|
|
106
|
+
accessorFn = (originalRow: TData) => {
|
|
107
|
+
let result = originalRow as Record<string, any>
|
|
108
|
+
|
|
109
|
+
for (const key of accessorKey.split('.')) {
|
|
110
|
+
result = result[key]
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return result
|
|
114
|
+
}
|
|
115
|
+
} else {
|
|
116
|
+
accessorFn = (originalRow: TData) =>
|
|
117
|
+
(originalRow as any)[resolvedColumnDef.accessorKey]
|
|
118
|
+
}
|
|
110
119
|
}
|
|
111
120
|
|
|
112
121
|
if (!id) {
|
|
@@ -125,7 +134,7 @@ export function createColumn<TData extends RowData, TValue>(
|
|
|
125
134
|
accessorFn,
|
|
126
135
|
parent: parent as any,
|
|
127
136
|
depth,
|
|
128
|
-
columnDef: resolvedColumnDef as ColumnDef<TData>,
|
|
137
|
+
columnDef: resolvedColumnDef as ColumnDef<TData, any>,
|
|
129
138
|
columns: [],
|
|
130
139
|
getFlatColumns: memo(
|
|
131
140
|
() => [true],
|
package/src/core/headers.ts
CHANGED
|
@@ -8,6 +8,12 @@ export type CoreHeaderGroup<TData extends RowData> = {
|
|
|
8
8
|
headers: Header<TData, unknown>[]
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
+
export type HeaderContext<TData, TValue> = {
|
|
12
|
+
table: Table<TData>
|
|
13
|
+
header: Header<TData, TValue>
|
|
14
|
+
column: Column<TData, TValue>
|
|
15
|
+
}
|
|
16
|
+
|
|
11
17
|
export type CoreHeader<TData extends RowData, TValue> = {
|
|
12
18
|
id: string
|
|
13
19
|
index: number
|
|
@@ -20,11 +26,7 @@ export type CoreHeader<TData extends RowData, TValue> = {
|
|
|
20
26
|
getLeafHeaders: () => Header<TData, unknown>[]
|
|
21
27
|
isPlaceholder: boolean
|
|
22
28
|
placeholderId?: string
|
|
23
|
-
getContext: () =>
|
|
24
|
-
table: Table<TData>
|
|
25
|
-
header: Header<TData, TValue>
|
|
26
|
-
column: Column<TData, TValue>
|
|
27
|
-
}
|
|
29
|
+
getContext: () => HeaderContext<TData, TValue>
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
export type HeadersInstance<TData extends RowData> = {
|
|
@@ -78,7 +80,7 @@ function createHeader<TData extends RowData, TValue>(
|
|
|
78
80
|
getLeafHeaders: (): Header<TData, unknown>[] => {
|
|
79
81
|
const leafHeaders: Header<TData, unknown>[] = []
|
|
80
82
|
|
|
81
|
-
const recurseHeader = (h: CoreHeader<TData,
|
|
83
|
+
const recurseHeader = (h: CoreHeader<TData, any>) => {
|
|
82
84
|
if (h.subHeaders && h.subHeaders.length) {
|
|
83
85
|
h.subHeaders.map(recurseHeader)
|
|
84
86
|
}
|
package/src/core/table.ts
CHANGED
|
@@ -80,8 +80,8 @@ export type CoreOptions<TData extends RowData> = {
|
|
|
80
80
|
getCoreRowModel: (table: Table<any>) => () => RowModel<any>
|
|
81
81
|
getSubRows?: (originalRow: TData, index: number) => undefined | TData[]
|
|
82
82
|
getRowId?: (originalRow: TData, index: number, parent?: Row<TData>) => string
|
|
83
|
-
columns: ColumnDef<TData>[]
|
|
84
|
-
defaultColumn?: Partial<ColumnDef<TData>>
|
|
83
|
+
columns: ColumnDef<TData, any>[]
|
|
84
|
+
defaultColumn?: Partial<ColumnDef<TData, unknown>>
|
|
85
85
|
renderFallbackValue: any
|
|
86
86
|
}
|
|
87
87
|
|
|
@@ -99,8 +99,8 @@ export type CoreInstance<TData extends RowData> = {
|
|
|
99
99
|
_getCoreRowModel?: () => RowModel<TData>
|
|
100
100
|
getRowModel: () => RowModel<TData>
|
|
101
101
|
getRow: (id: string) => Row<TData>
|
|
102
|
-
_getDefaultColumnDef: () => Partial<ColumnDef<TData>>
|
|
103
|
-
_getColumnDefs: () => ColumnDef<TData>[]
|
|
102
|
+
_getDefaultColumnDef: () => Partial<ColumnDef<TData, unknown>>
|
|
103
|
+
_getColumnDefs: () => ColumnDef<TData, unknown>[]
|
|
104
104
|
_getAllFlatColumnsById: () => Record<string, Column<TData, unknown>>
|
|
105
105
|
getAllColumns: () => Column<TData, unknown>[]
|
|
106
106
|
getAllFlatColumns: () => Column<TData, unknown>[]
|
|
@@ -227,7 +227,9 @@ export function createTable<TData extends RowData>(
|
|
|
227
227
|
_getDefaultColumnDef: memo(
|
|
228
228
|
() => [table.options.defaultColumn],
|
|
229
229
|
defaultColumn => {
|
|
230
|
-
defaultColumn = (defaultColumn ?? {}) as Partial<
|
|
230
|
+
defaultColumn = (defaultColumn ?? {}) as Partial<
|
|
231
|
+
ColumnDef<TData, unknown>
|
|
232
|
+
>
|
|
231
233
|
|
|
232
234
|
return {
|
|
233
235
|
header: props => props.header.column.id,
|
|
@@ -237,7 +239,7 @@ export function createTable<TData extends RowData>(
|
|
|
237
239
|
return Object.assign(obj, feature.getDefaultColumnDef?.())
|
|
238
240
|
}, {}),
|
|
239
241
|
...defaultColumn,
|
|
240
|
-
} as Partial<ColumnDef<TData>>
|
|
242
|
+
} as Partial<ColumnDef<TData, unknown>>
|
|
241
243
|
},
|
|
242
244
|
{
|
|
243
245
|
debug: () => table.options.debugAll ?? table.options.debugColumns,
|
|
@@ -251,7 +253,7 @@ export function createTable<TData extends RowData>(
|
|
|
251
253
|
() => [table._getColumnDefs()],
|
|
252
254
|
columnDefs => {
|
|
253
255
|
const recurseColumns = (
|
|
254
|
-
columnDefs: ColumnDef<TData>[],
|
|
256
|
+
columnDefs: ColumnDef<TData, unknown>[],
|
|
255
257
|
parent?: Column<TData, unknown>,
|
|
256
258
|
depth = 0
|
|
257
259
|
): Column<TData, unknown>[] => {
|
|
@@ -218,9 +218,11 @@ export const Expanding: TableFeature = {
|
|
|
218
218
|
},
|
|
219
219
|
getCanExpand: () => {
|
|
220
220
|
return (
|
|
221
|
-
|
|
222
|
-
(
|
|
223
|
-
|
|
221
|
+
table.options.getRowCanExpand?.(row) ??
|
|
222
|
+
(
|
|
223
|
+
(table.options.enableExpanding ?? true) &&
|
|
224
|
+
!!row.subRows?.length
|
|
225
|
+
)
|
|
224
226
|
)
|
|
225
227
|
},
|
|
226
228
|
getToggleExpandedHandler: () => {
|
package/src/features/Filters.ts
CHANGED
package/src/index.ts
CHANGED
|
@@ -16,6 +16,7 @@ export * from './features/Visibility'
|
|
|
16
16
|
export * from './filterFns'
|
|
17
17
|
export * from './sortingFns'
|
|
18
18
|
export * from './aggregationFns'
|
|
19
|
+
export * from './columnHelper'
|
|
19
20
|
export * from './utils'
|
|
20
21
|
export * from './utils/getCoreRowModel'
|
|
21
22
|
export * from './utils/getFilteredRowModel'
|
package/src/utils.ts
CHANGED
|
@@ -15,7 +15,57 @@ export type UnionToIntersection<T> = (
|
|
|
15
15
|
? R
|
|
16
16
|
: never
|
|
17
17
|
|
|
18
|
-
export type
|
|
18
|
+
export type IsAny<T, Y, N> = 1 extends 0 & T ? Y : N
|
|
19
|
+
export type IsKnown<T, Y, N> = unknown extends T ? N : Y
|
|
20
|
+
|
|
21
|
+
type ComputeRange<
|
|
22
|
+
N extends number,
|
|
23
|
+
Result extends Array<unknown> = []
|
|
24
|
+
> = Result['length'] extends N
|
|
25
|
+
? Result
|
|
26
|
+
: ComputeRange<N, [...Result, Result['length']]>
|
|
27
|
+
type Index100 = ComputeRange<100>[number]
|
|
28
|
+
|
|
29
|
+
// Is this type a tuple?
|
|
30
|
+
type IsTuple<T> = T extends readonly any[] & { length: infer Length }
|
|
31
|
+
? Length extends Index100
|
|
32
|
+
? T
|
|
33
|
+
: never
|
|
34
|
+
: never
|
|
35
|
+
|
|
36
|
+
// If this type is a tuple, what indices are allowed?
|
|
37
|
+
type AllowedIndexes<
|
|
38
|
+
Tuple extends ReadonlyArray<any>,
|
|
39
|
+
Keys extends number = never
|
|
40
|
+
> = Tuple extends readonly []
|
|
41
|
+
? Keys
|
|
42
|
+
: Tuple extends readonly [infer _, ...infer Tail]
|
|
43
|
+
? AllowedIndexes<Tail, Keys | Tail['length']>
|
|
44
|
+
: Keys
|
|
45
|
+
|
|
46
|
+
export type DeepKeys<T> = unknown extends T
|
|
47
|
+
? keyof T
|
|
48
|
+
: object extends T
|
|
49
|
+
? string
|
|
50
|
+
: T extends readonly any[] & IsTuple<T>
|
|
51
|
+
? AllowedIndexes<T> | DeepKeysPrefix<T, AllowedIndexes<T>>
|
|
52
|
+
: T extends any[]
|
|
53
|
+
? never & 'Dynamic length array indexing is not supported'
|
|
54
|
+
: T extends object
|
|
55
|
+
? (keyof T & string) | DeepKeysPrefix<T, keyof T>
|
|
56
|
+
: never
|
|
57
|
+
|
|
58
|
+
type DeepKeysPrefix<T, TPrefix> = TPrefix extends keyof T & (number | string)
|
|
59
|
+
? `${TPrefix}.${DeepKeys<T[TPrefix]> & string}`
|
|
60
|
+
: never
|
|
61
|
+
|
|
62
|
+
export type DeepValue<T, TProp> = T extends Record<string | number, any>
|
|
63
|
+
? TProp extends `${infer TBranch}.${infer TDeepProp}`
|
|
64
|
+
? DeepValue<T[TBranch], TDeepProp>
|
|
65
|
+
: T[TProp & string]
|
|
66
|
+
: never
|
|
67
|
+
|
|
68
|
+
///
|
|
19
69
|
|
|
20
70
|
export function functionalUpdate<T>(updater: Updater<T>, input: T): T {
|
|
21
71
|
return typeof updater === 'function'
|