chore: workspace improvements (#282)

This commit is contained in:
rahim
2026-01-04 01:39:26 +11:00
committed by GitHub
parent d74e4e6701
commit 2901593085
77 changed files with 2085 additions and 573 deletions
+2
View File
@@ -0,0 +1,2 @@
export { pick } from './pick';
export { getSelectorKeys, type Selector } from './selector';
+18
View File
@@ -0,0 +1,18 @@
/**
* Creates a new object with only the specified keys.
*
* @example
* const obj = { a: 1, b: 2, c: 3 };
* pick(obj, ['a', 'c']); // { a: 1, c: 3 }
*/
export function pick<T extends Record<string, unknown>, K extends keyof T>(obj: T, keys: readonly K[]): Pick<T, K> {
const result = {} as Pick<T, K>;
for (const key of keys) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
result[key] = obj[key];
}
}
return result;
}
+33
View File
@@ -0,0 +1,33 @@
import { isObject } from '../predicate/predicate';
/**
* A function that selects a subset of state.
*/
export type Selector<State, Selected> = (state: State) => Selected;
/**
* Extracts the state keys a selector depends on by running it once
* and inspecting the result object's keys.
*
* Returns `null` if the selector returns a primitive or array
* (keys cannot be determined).
*
* @example
* const selector = (s: State) => ({ volume: s.volume, muted: s.muted });
* getSelectorKeys(selector, state); // ['volume', 'muted']
*
* const primitiveSelector = (s: State) => s.volume;
* getSelectorKeys(primitiveSelector, state); // null
*/
export function getSelectorKeys<State, Selected>(
selector: Selector<State, Selected>,
state: State,
): (keyof State)[] | null {
const result = selector(state);
if (!isObject(result) || Array.isArray(result)) {
return null;
}
return Object.keys(result) as (keyof State)[];
}
@@ -0,0 +1,60 @@
import { describe, expect, it } from 'vitest';
import { pick } from '../pick';
describe('pick', () => {
it('picks specified keys from object', () => {
const obj = { a: 1, b: 2, c: 3 };
expect(pick(obj, ['a', 'c'])).toEqual({ a: 1, c: 3 });
});
it('picks single key', () => {
const obj = { a: 1, b: 2, c: 3 };
expect(pick(obj, ['b'])).toEqual({ b: 2 });
});
it('returns empty object for empty keys array', () => {
const obj = { a: 1, b: 2 };
expect(pick(obj, [])).toEqual({});
});
it('ignores non-existent keys', () => {
const obj = { a: 1, b: 2 } as Record<string, number>;
expect(pick(obj, ['a', 'nonexistent'] as (keyof typeof obj)[])).toEqual({ a: 1 });
});
it('handles nested objects (shallow copy)', () => {
const nested = { a: { x: 1 }, b: { y: 2 } };
const result = pick(nested, ['a']);
expect(result).toEqual({ a: { x: 1 } });
expect(result.a).toBe(nested.a); // Same reference (shallow)
});
it('handles all keys', () => {
const obj = { a: 1, b: 2 };
expect(pick(obj, ['a', 'b'])).toEqual({ a: 1, b: 2 });
});
it('preserves value types', () => {
const obj = {
str: 'hello',
num: 42,
bool: true,
arr: [1, 2, 3],
nil: null,
undef: undefined,
};
const result = pick(obj, ['str', 'num', 'bool', 'arr', 'nil', 'undef']);
expect(result).toEqual(obj);
});
it('works with readonly keys array', () => {
const obj = { a: 1, b: 2, c: 3 };
const keys = ['a', 'c'] as const;
expect(pick(obj, keys)).toEqual({ a: 1, c: 3 });
});
});
@@ -0,0 +1,83 @@
import { describe, expect, it } from 'vitest';
import { getSelectorKeys } from '../selector';
describe('getSelectorKeys', () => {
interface State {
volume: number;
muted: boolean;
currentTime: number;
}
const state: State = { volume: 1, muted: false, currentTime: 0 };
it('extracts keys from object selector result', () => {
const selector = (s: State) => ({ volume: s.volume, muted: s.muted });
expect(getSelectorKeys(selector, state)).toEqual(['volume', 'muted']);
});
it('extracts single key', () => {
const selector = (s: State) => ({ volume: s.volume });
expect(getSelectorKeys(selector, state)).toEqual(['volume']);
});
it('returns null for primitive selector result (number)', () => {
const selector = (s: State) => s.volume;
expect(getSelectorKeys(selector, state)).toBeNull();
});
it('returns null for primitive selector result (boolean)', () => {
const selector = (s: State) => s.muted;
expect(getSelectorKeys(selector, state)).toBeNull();
});
it('returns null for primitive selector result (string)', () => {
const selector = () => 'hello';
expect(getSelectorKeys(selector, state)).toBeNull();
});
it('returns null for array selector result', () => {
const selector = (s: State) => [s.volume, s.muted];
expect(getSelectorKeys(selector, state)).toBeNull();
});
it('returns null for null selector result', () => {
const selector = () => null;
expect(getSelectorKeys(selector, state)).toBeNull();
});
it('returns null for undefined selector result', () => {
const selector = () => undefined;
expect(getSelectorKeys(selector, state)).toBeNull();
});
it('returns empty array for empty object selector', () => {
const selector = () => ({});
expect(getSelectorKeys(selector, state)).toEqual([]);
});
it('handles derived/computed properties in selector', () => {
const selector = (s: State) => ({
volumePercent: Math.round(s.volume * 100),
isMuted: s.muted,
});
// Returns the result object's keys, not the state keys accessed
expect(getSelectorKeys(selector, state)).toEqual(['volumePercent', 'isMuted']);
});
it('handles selector that accesses nested state', () => {
interface NestedState {
audio: { volume: number; muted: boolean };
video: { quality: string };
}
const nestedState: NestedState = {
audio: { volume: 1, muted: false },
video: { quality: 'hd' },
};
const selector = (s: NestedState) => ({ audio: s.audio });
expect(getSelectorKeys(selector, nestedState)).toEqual(['audio']);
});
});