pond-ts 0.28.0 → 0.29.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/CHANGELOG.md +31 -1
- package/dist/batch/by-column.d.ts +1 -0
- package/dist/batch/by-column.js +39 -15
- package/dist/batch/time-series.d.ts +5 -2
- package/dist/batch/time-series.js +9 -2
- package/dist/reducers/index.js +5 -0
- package/dist/schema/aggregate.d.ts +3 -3
- package/dist/schema/events.d.ts +3 -1
- package/dist/schema/reduce.d.ts +1 -1
- package/dist/schema/rolling.d.ts +1 -1
- package/dist/schema/series.d.ts +19 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,7 +7,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
|
7
7
|
file covers both packages. Pre-1.0: minor bumps may include new features and
|
|
8
8
|
type-level changes; patch bumps are strictly additive.
|
|
9
9
|
|
|
10
|
-
[Unreleased]: https://github.com/pjm17971/pond-ts/compare/v0.
|
|
10
|
+
[Unreleased]: https://github.com/pjm17971/pond-ts/compare/v0.29.0...HEAD
|
|
11
|
+
[0.29.0]: https://github.com/pjm17971/pond-ts/compare/v0.28.0...v0.29.0
|
|
11
12
|
[0.28.0]: https://github.com/pjm17971/pond-ts/compare/v0.27.0...v0.28.0
|
|
12
13
|
[0.27.0]: https://github.com/pjm17971/pond-ts/compare/v0.26.0...v0.27.0
|
|
13
14
|
[0.26.0]: https://github.com/pjm17971/pond-ts/compare/v0.25.0...v0.26.0
|
|
@@ -22,6 +23,35 @@ type-level changes; patch bumps are strictly additive.
|
|
|
22
23
|
|
|
23
24
|
## [Unreleased]
|
|
24
25
|
|
|
26
|
+
## [0.29.0] — 2026-06-17
|
|
27
|
+
|
|
28
|
+
### Added
|
|
29
|
+
|
|
30
|
+
- **`byColumn({ edges, inclusive })`** — `inclusive: '(]'` makes edge bins
|
|
31
|
+
upper-inclusive (`(eᵢ, eᵢ₊₁]`), for Coggan power / HR zones where a sample on a
|
|
32
|
+
zone's top edge belongs to the lower zone (the first edge becomes an exclusive
|
|
33
|
+
floor). Defaults to `'[)'` (unchanged — lower-inclusive `[eᵢ, eᵢ₊₁)`). (estela
|
|
34
|
+
F-geo-2 zone inclusivity.)
|
|
35
|
+
- **`'mean'` reducer alias for `'avg'`** — `'mean'` is now an accepted built-in
|
|
36
|
+
reducer name across `aggregate` / `rolling` / `byColumn` / `rollingByColumn` /
|
|
37
|
+
`reduce` (and the live equivalents), at **both runtime and the type level**: it
|
|
38
|
+
resolves to the `avg` kernel and classifies as numeric output
|
|
39
|
+
(`number | undefined`), exactly like `'avg'`. Matches the column API's
|
|
40
|
+
`Float64Column.mean()`. (estela F-reducer-naming.)
|
|
41
|
+
|
|
42
|
+
### Fixed
|
|
43
|
+
|
|
44
|
+
- **`RowForSchema` honors `required: false`** — a **value** column declared
|
|
45
|
+
`required: false` now accepts `undefined` in its tuple-row cell at the type
|
|
46
|
+
level (matching the runtime, which records it as missing), so optional cells no
|
|
47
|
+
longer need an `as never` cast. The **key (first) column stays required** even
|
|
48
|
+
if marked `required: false` (the constructor always requires it). `null` is
|
|
49
|
+
still not admitted for tuple rows (only the JSON object-row path takes `null`).
|
|
50
|
+
Correspondingly, **`.rows` / `toRows()` now type an optional cell as
|
|
51
|
+
`… | undefined`** (`NormalizedRowForSchema`), so reading a possibly-missing
|
|
52
|
+
cell is no longer unsoundly typed as present — a type tightening on output for
|
|
53
|
+
schemas that use `required: false`. (estela F-geo-row-optional; Codex-hardened.)
|
|
54
|
+
|
|
25
55
|
## [0.28.0] — 2026-06-17
|
|
26
56
|
|
|
27
57
|
### Added
|
package/dist/batch/by-column.js
CHANGED
|
@@ -45,21 +45,45 @@ export function computeByColumn(store, binColName, spec, columnSpecs) {
|
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
const last = edges.length - 1;
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
48
|
+
// `inclusive` picks the bin a value exactly on an interior edge falls into.
|
|
49
|
+
// `'[)'` (default): bins are `[eᵢ, eᵢ₊₁)`, lower-inclusive — a boundary value
|
|
50
|
+
// goes to the bin ABOVE; range is `[e₀, eₙ)`. `'(]'`: bins are `(eᵢ, eᵢ₊₁]`,
|
|
51
|
+
// upper-inclusive (Coggan power/HR zones — a sample at exactly a zone's top
|
|
52
|
+
// edge is the LOWER zone) — a boundary value goes to the bin BELOW; range is
|
|
53
|
+
// `(e₀, eₙ]`, so the first edge is an exclusive floor (set it below your
|
|
54
|
+
// minimum to keep the minimum in bin 0).
|
|
55
|
+
binOf =
|
|
56
|
+
spec.inclusive === '(]'
|
|
57
|
+
? (v) => {
|
|
58
|
+
if (v <= edges[0] || v > edges[last])
|
|
59
|
+
return NaN; // out of (e₀, eₙ]
|
|
60
|
+
// rightmost edge STRICTLY less than v, clamped to a valid bin [0, last)
|
|
61
|
+
let lo = 0;
|
|
62
|
+
let hi = last;
|
|
63
|
+
while (lo < hi) {
|
|
64
|
+
const mid = (lo + hi + 1) >>> 1;
|
|
65
|
+
if (edges[mid] < v)
|
|
66
|
+
lo = mid;
|
|
67
|
+
else
|
|
68
|
+
hi = mid - 1;
|
|
69
|
+
}
|
|
70
|
+
return lo;
|
|
71
|
+
}
|
|
72
|
+
: (v) => {
|
|
73
|
+
if (v < edges[0] || v >= edges[last])
|
|
74
|
+
return NaN; // out of [e₀, eₙ)
|
|
75
|
+
// rightmost edge <= v, clamped to a valid bin [0, last)
|
|
76
|
+
let lo = 0;
|
|
77
|
+
let hi = last;
|
|
78
|
+
while (lo < hi) {
|
|
79
|
+
const mid = (lo + hi + 1) >>> 1;
|
|
80
|
+
if (edges[mid] <= v)
|
|
81
|
+
lo = mid;
|
|
82
|
+
else
|
|
83
|
+
hi = mid - 1;
|
|
84
|
+
}
|
|
85
|
+
return lo;
|
|
86
|
+
};
|
|
63
87
|
rangeOf = (i) => ({ start: edges[i], end: edges[i + 1] });
|
|
64
88
|
}
|
|
65
89
|
else {
|
|
@@ -539,8 +539,11 @@ export declare class TimeSeries<S extends SeriesSchema> {
|
|
|
539
539
|
* source (cumulative distance / work) yields contiguous ranges (per-km
|
|
540
540
|
* splits, elevation-vs-distance profile); a non-monotonic source (power)
|
|
541
541
|
* yields a histogram (distribution).
|
|
542
|
-
* - `{ edges }` — explicit ascending edges `[e₀ … eₙ]` → `n` bins
|
|
543
|
-
* `[
|
|
542
|
+
* - `{ edges, inclusive? }` — explicit ascending edges `[e₀ … eₙ]` → `n` bins.
|
|
543
|
+
* `inclusive` defaults to `'[)'` (bin `i` = `[eᵢ, eᵢ₊₁)`, lower-inclusive);
|
|
544
|
+
* pass `'(]'` for upper-inclusive bins (`(eᵢ, eᵢ₊₁]`) — Coggan power / HR
|
|
545
|
+
* zones, where a sample exactly on a zone's top edge belongs to the lower
|
|
546
|
+
* zone (the first edge becomes an exclusive floor). Always emits all `n` bins.
|
|
544
547
|
*
|
|
545
548
|
* A row whose bin value is missing / non-finite (or, for `edges`, outside
|
|
546
549
|
* `[e₀, eₙ)`) contributes to no bin. The reducer non-finite policy still
|
|
@@ -872,6 +872,10 @@ export class TimeSeries {
|
|
|
872
872
|
}
|
|
873
873
|
/** Example: `series.rows`. Returns the normalized row view of the series. */
|
|
874
874
|
get rows() {
|
|
875
|
+
// `toRows` returns runtime-normalized rows (Time/Interval keys, `undefined`
|
|
876
|
+
// for missing cells); the double cast is the existing trust point — the
|
|
877
|
+
// `RowForSchema`→`NormalizedRowForSchema` conditional types no longer overlap
|
|
878
|
+
// structurally for a direct cast now that both honor `required: false`.
|
|
875
879
|
return toRows(this.schema, this.events);
|
|
876
880
|
}
|
|
877
881
|
/** Example: `series.toRows()`. Returns normalized row arrays using `Time`/`TimeRange`/`Interval` keys and `undefined` for missing payload values. */
|
|
@@ -1391,8 +1395,11 @@ export class TimeSeries {
|
|
|
1391
1395
|
* source (cumulative distance / work) yields contiguous ranges (per-km
|
|
1392
1396
|
* splits, elevation-vs-distance profile); a non-monotonic source (power)
|
|
1393
1397
|
* yields a histogram (distribution).
|
|
1394
|
-
* - `{ edges }` — explicit ascending edges `[e₀ … eₙ]` → `n` bins
|
|
1395
|
-
* `[
|
|
1398
|
+
* - `{ edges, inclusive? }` — explicit ascending edges `[e₀ … eₙ]` → `n` bins.
|
|
1399
|
+
* `inclusive` defaults to `'[)'` (bin `i` = `[eᵢ, eᵢ₊₁)`, lower-inclusive);
|
|
1400
|
+
* pass `'(]'` for upper-inclusive bins (`(eᵢ, eᵢ₊₁]`) — Coggan power / HR
|
|
1401
|
+
* zones, where a sample exactly on a zone's top edge belongs to the lower
|
|
1402
|
+
* zone (the first edge becomes an exclusive floor). Always emits all `n` bins.
|
|
1396
1403
|
*
|
|
1397
1404
|
* A row whose bin value is missing / non-finite (or, for `edges`, outside
|
|
1398
1405
|
* `[e₀, eₙ)`) contributes to no bin. The reducer non-finite policy still
|
package/dist/reducers/index.js
CHANGED
|
@@ -33,6 +33,11 @@ export function resolveReducer(operation) {
|
|
|
33
33
|
const r = registry[operation];
|
|
34
34
|
if (r)
|
|
35
35
|
return r;
|
|
36
|
+
// `'mean'` is an accepted alias for `'avg'` in aggregate/rolling mappings,
|
|
37
|
+
// matching the column API (`Float64Column.mean()` → the `'avg'` kernel). Keeps
|
|
38
|
+
// the registry free of a duplicate entry. (estela F-reducer-naming.)
|
|
39
|
+
if (operation === 'mean')
|
|
40
|
+
return avg;
|
|
36
41
|
const q = parsePercentile(operation);
|
|
37
42
|
if (q !== undefined)
|
|
38
43
|
return percentileReducer(q);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AppendColumn, ArrayColumnNameForSchema, ColumnDef, ColumnValue, OptionalizeColumns, ReplaceColumnKind, ScalarKind, SeriesSchema, ValueColumn, ValueColumnsForSchema } from './series.js';
|
|
2
|
-
export type AggregateFunction = 'sum' | 'avg' | 'min' | 'max' | 'count' | 'first' | 'last' | 'median' | 'stdev' | 'difference' | 'keep' | 'unique' | 'samples' | `p${number}` | `top${number}`;
|
|
2
|
+
export type AggregateFunction = 'sum' | 'avg' | 'mean' | 'min' | 'max' | 'count' | 'first' | 'last' | 'median' | 'stdev' | 'difference' | 'keep' | 'unique' | 'samples' | `p${number}` | `top${number}`;
|
|
3
3
|
/**
|
|
4
4
|
* Custom aggregate reducers receive every value in a bucket (including
|
|
5
5
|
* `undefined`) and return a single result. The return type is widened to
|
|
@@ -152,7 +152,7 @@ type UnifiedOutputKind<Columns extends readonly ValueColumn[], K extends string,
|
|
|
152
152
|
* reducer function (or otherwise unrecognized) — the spec branch passes
|
|
153
153
|
* `ScalarKind`, the shorthand branch passes the source column's kind.
|
|
154
154
|
*/
|
|
155
|
-
type ReducerOutputKind<Columns extends readonly ValueColumn[], From extends string, Using, Fallback extends ScalarKind> = Using extends 'sum' | 'avg' | 'count' | 'min' | 'max' | 'median' | 'stdev' | 'difference' | `p${number}` ? 'number' : Using extends 'unique' | 'samples' | `top${number}` ? 'array' : Using extends 'first' | 'last' | 'keep' ? From extends Columns[number]['name'] ? ColumnKindByName<Columns, From> : ScalarKind : Fallback;
|
|
155
|
+
type ReducerOutputKind<Columns extends readonly ValueColumn[], From extends string, Using, Fallback extends ScalarKind> = Using extends 'sum' | 'avg' | 'mean' | 'count' | 'min' | 'max' | 'median' | 'stdev' | 'difference' | `p${number}` ? 'number' : Using extends 'unique' | 'samples' | `top${number}` ? 'array' : Using extends 'first' | 'last' | 'keep' ? From extends Columns[number]['name'] ? ColumnKindByName<Columns, From> : ScalarKind : Fallback;
|
|
156
156
|
/**
|
|
157
157
|
* Union of typed `ColumnDef`s — one per **output key** in the mapping
|
|
158
158
|
* (not per source column). Used as the `...Rest` of the schema tuple;
|
|
@@ -209,7 +209,7 @@ export type AggregateOutputMapResultSchema<S extends SeriesSchema, Mapping> = Ag
|
|
|
209
209
|
* Aggregate functions that always produce a numeric result regardless of
|
|
210
210
|
* source column kind. Matches the reducer registry's `outputKind: 'number'`.
|
|
211
211
|
*/
|
|
212
|
-
type NumericAggregateFunction = 'sum' | 'avg' | 'count' | 'min' | 'max' | 'median' | 'stdev' | 'difference' | `p${number}`;
|
|
212
|
+
type NumericAggregateFunction = 'sum' | 'avg' | 'mean' | 'count' | 'min' | 'max' | 'median' | 'stdev' | 'difference' | `p${number}`;
|
|
213
213
|
/**
|
|
214
214
|
* Output column kind for `arrayAggregate(col, reducer, { kind? })`.
|
|
215
215
|
* Numeric reducers → `'number'`, `'unique'` → `'array'`, `'first'`/`'last'`/
|
package/dist/schema/events.d.ts
CHANGED
|
@@ -20,7 +20,9 @@ export type TimeSeriesInput<S extends SeriesSchema> = {
|
|
|
20
20
|
sort?: boolean;
|
|
21
21
|
};
|
|
22
22
|
export type NormalizedRowForSchema<S extends readonly ColumnDef<string, string>[]> = {
|
|
23
|
-
[I in keyof S]: S[I] extends ColumnDef<any, infer K> ? NormalizedValueForKind<K> :
|
|
23
|
+
[I in keyof S]: S[I] extends ColumnDef<any, infer K> ? I extends '0' ? NormalizedValueForKind<K> : S[I] extends {
|
|
24
|
+
required: false;
|
|
25
|
+
} ? NormalizedValueForKind<K> | undefined : NormalizedValueForKind<K> : never;
|
|
24
26
|
};
|
|
25
27
|
type DataValueForColumn<C extends ColumnDef<string, string>> = C extends ColumnDef<any, infer K> ? C['required'] extends false ? NormalizedValueForKind<K> | undefined : NormalizedValueForKind<K> : never;
|
|
26
28
|
type NormalizedDataValueForColumn<C extends ColumnDef<string, string>> = C extends ColumnDef<any, infer K> ? K extends FirstColKind ? EventKeyForKind<K> : C['required'] extends false ? NormalizedValueForKind<K> | undefined : NormalizedValueForKind<K> : never;
|
package/dist/schema/reduce.d.ts
CHANGED
|
@@ -73,7 +73,7 @@ export type ReduceResult<S extends SeriesSchema, Mapping> = {
|
|
|
73
73
|
* and shorthand branches. `From` is the spec's `from` or the shorthand
|
|
74
74
|
* key; `Using` is the reducer.
|
|
75
75
|
*/
|
|
76
|
-
type ReduceValueForReducer<S extends SeriesSchema, From extends string, Using> = Using extends 'sum' | 'avg' | 'count' | 'min' | 'max' | 'median' | 'stdev' | 'difference' | `p${number}` ? number | undefined : Using extends 'unique' | 'samples' | `top${number}` ? From extends ValueColumnsForSchema<S>[number]['name'] ? ColumnByName<S, From>['kind'] extends 'number' ? ReadonlyArray<number> | undefined : ColumnByName<S, From>['kind'] extends 'string' ? ReadonlyArray<string> | undefined : ColumnByName<S, From>['kind'] extends 'boolean' ? ReadonlyArray<boolean> | undefined : ReadonlyArray<string | number | boolean> | undefined : ReadonlyArray<string | number | boolean> | undefined : Using extends 'first' | 'last' | 'keep' ? From extends ValueColumnsForSchema<S>[number]['name'] ? ColumnByName<S, From>['kind'] extends 'number' ? number | undefined : ColumnByName<S, From>['kind'] extends 'string' ? string | undefined : ColumnByName<S, From>['kind'] extends 'boolean' ? boolean | undefined : ColumnValue | undefined : ColumnValue | undefined : ColumnValue | undefined;
|
|
76
|
+
type ReduceValueForReducer<S extends SeriesSchema, From extends string, Using> = Using extends 'sum' | 'avg' | 'mean' | 'count' | 'min' | 'max' | 'median' | 'stdev' | 'difference' | `p${number}` ? number | undefined : Using extends 'unique' | 'samples' | `top${number}` ? From extends ValueColumnsForSchema<S>[number]['name'] ? ColumnByName<S, From>['kind'] extends 'number' ? ReadonlyArray<number> | undefined : ColumnByName<S, From>['kind'] extends 'string' ? ReadonlyArray<string> | undefined : ColumnByName<S, From>['kind'] extends 'boolean' ? ReadonlyArray<boolean> | undefined : ReadonlyArray<string | number | boolean> | undefined : ReadonlyArray<string | number | boolean> | undefined : Using extends 'first' | 'last' | 'keep' ? From extends ValueColumnsForSchema<S>[number]['name'] ? ColumnByName<S, From>['kind'] extends 'number' ? number | undefined : ColumnByName<S, From>['kind'] extends 'string' ? string | undefined : ColumnByName<S, From>['kind'] extends 'boolean' ? boolean | undefined : ColumnValue | undefined : ColumnValue | undefined : ColumnValue | undefined;
|
|
77
77
|
/**
|
|
78
78
|
* Value type for an explicit `kind` on a reduce spec. Mirrors
|
|
79
79
|
* `NormalizedValueForKind` but stays inline here for the same TS2394
|
package/dist/schema/rolling.d.ts
CHANGED
|
@@ -90,7 +90,7 @@ type FusedColumnKind<S extends SeriesSchema, Key extends string, Value> = Value
|
|
|
90
90
|
* Reducer-string-to-output-kind dispatch, shared by both AggregateMap
|
|
91
91
|
* and AggregateOutputMap entry shapes.
|
|
92
92
|
*/
|
|
93
|
-
type FusedReducerKind<S extends SeriesSchema, From extends string, Using> = Using extends 'sum' | 'avg' | 'count' | 'min' | 'max' | 'median' | 'stdev' | 'difference' | `p${number}` ? 'number' : Using extends 'unique' | 'samples' | `top${number}` ? 'array' : Using extends 'first' | 'last' | 'keep' ? FromColumnKind<S, From> : ScalarKind;
|
|
93
|
+
type FusedReducerKind<S extends SeriesSchema, From extends string, Using> = Using extends 'sum' | 'avg' | 'mean' | 'count' | 'min' | 'max' | 'median' | 'stdev' | 'difference' | `p${number}` ? 'number' : Using extends 'unique' | 'samples' | `top${number}` ? 'array' : Using extends 'first' | 'last' | 'keep' ? FromColumnKind<S, From> : ScalarKind;
|
|
94
94
|
/**
|
|
95
95
|
* Look up the kind of a value column by name. Used by source-
|
|
96
96
|
* preserving reducers (`first` / `last` / `keep`) where the output
|
package/dist/schema/series.d.ts
CHANGED
|
@@ -22,6 +22,14 @@ export type ColumnDef<Name extends string, Kind extends string> = {
|
|
|
22
22
|
kind: Kind;
|
|
23
23
|
required?: boolean;
|
|
24
24
|
};
|
|
25
|
+
/**
|
|
26
|
+
* The key (first) column of a schema. Its **name must equal its kind** —
|
|
27
|
+
* `time` / `timeRange` / `interval`. So `{ name: 'time', kind: 'time' }` is the
|
|
28
|
+
* only valid time key; `{ name: 'at', kind: 'time' }` does **not** typecheck
|
|
29
|
+
* (the error surfaces as a name/literal-type mismatch, e.g. `'"at"' is not
|
|
30
|
+
* assignable to '"time"'` — read it as "the key column must be named for its
|
|
31
|
+
* kind", not as a value error). Value columns, by contrast, take any name.
|
|
32
|
+
*/
|
|
25
33
|
export type FirstColumn = ColumnDef<'time', 'time'> | ColumnDef<'interval', 'interval'> | ColumnDef<'timeRange', 'timeRange'>;
|
|
26
34
|
export type ValueColumn<Name extends string = string> = ColumnDef<Name, ScalarKind>;
|
|
27
35
|
export type SeriesSchema = readonly [FirstColumn, ...ValueColumn[]];
|
|
@@ -32,8 +40,18 @@ export type ValueColumnsForSchema<S extends SeriesSchema> = S extends readonly [
|
|
|
32
40
|
export type ValueForKind<K extends string> = K extends 'time' ? TimestampInput | Time : K extends 'interval' ? IntervalInput | Interval : K extends 'timeRange' ? TimeRangeInput | TimeRange : K extends 'number' ? number : K extends 'string' ? string : K extends 'boolean' ? boolean : K extends 'array' ? ArrayValue : never;
|
|
33
41
|
export type NormalizedValueForKind<K extends string> = K extends 'time' ? Time : K extends 'timeRange' ? TimeRange : K extends 'interval' ? Interval : K extends 'number' ? number : K extends 'string' ? string : K extends 'boolean' ? boolean : K extends 'array' ? ArrayValue : never;
|
|
34
42
|
export type KindForValue<V extends ScalarValue> = V extends number ? 'number' : V extends string ? 'string' : 'boolean';
|
|
43
|
+
/**
|
|
44
|
+
* Tuple-row input type for a schema. A column declared `required: false`
|
|
45
|
+
* accepts `undefined` in its cell (a missing value — the constructor records
|
|
46
|
+
* it in the validity bitmap), matching the runtime's intake. `null` is **not**
|
|
47
|
+
* admitted: the tuple-row constructor rejects it (only the JSON object-row path
|
|
48
|
+
* accepts `null`), so the type stays honest to what intake actually takes —
|
|
49
|
+
* pass `undefined` for a missing tuple cell. (estela F-geo-row-optional.)
|
|
50
|
+
*/
|
|
35
51
|
export type RowForSchema<S extends readonly ColumnDef<string, string>[]> = {
|
|
36
|
-
[I in keyof S]: S[I] extends ColumnDef<any, infer K> ? ValueForKind<K> :
|
|
52
|
+
[I in keyof S]: S[I] extends ColumnDef<any, infer K> ? I extends '0' ? ValueForKind<K> : S[I] extends {
|
|
53
|
+
required: false;
|
|
54
|
+
} ? ValueForKind<K> | undefined : ValueForKind<K> : never;
|
|
37
55
|
};
|
|
38
56
|
export type NumericColumnNameForSchema<S extends SeriesSchema> = Extract<ValueColumnsForSchema<S>[number], ColumnDef<string, 'number'>>['name'];
|
|
39
57
|
/**
|