Open Papooch opened 3 years ago
Ok, I have a proof of concept:
// pickable.ts
export type Primitive = string | number | boolean | bigint | null | void | symbol | Function;
export type Prev = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ...0[]];
export type Leaves<T, U extends string = never, L extends number = 1> = [
L,
] extends [never]
? U
: {
[K in keyof T & string]: [U] extends [never]
? T[K] extends Primitive
? K
: Leaves<T[K], K, Prev[L]>
: T[K] extends Primitive
? `${U}.${K}`
: Leaves<T[K], `${U}.${K}`, Prev[L]>;
}[keyof T & string];
export type ResolvePath<T, K> = K extends keyof T
? T[K]
: K extends `${infer F}.${infer L}`
? ResolvePath<ResolvePath<T, F>, L>
: never;
export type LastKey<T extends string> = T extends `${string}.${infer L}`
? LastKey<L & string>
: T;
export function cherryPick<T, K extends readonly Leaves<T>[]>(
obj: T,
keys: K | [],
): { [K2 in K[number] as LastKey<K2>]: ResolvePath<T, K2> } {
const ret = {} as any;
keys.forEach((key) => {
const path = key.split('.');
let prop = obj as any;
path.forEach((segment) => {
prop = prop[segment as keyof typeof prop];
});
ret[path.pop() as keyof typeof ret] = prop;
});
return ret;
}
export function makePickable<T>(
obj: T,
): <K extends readonly Leaves<T>[]>(
keys: K | [],
) => { [K2 in K[number] as LastKey<K2>]: ResolvePath<T, K2> } {
return (keys: any) => cherryPick(obj, keys) as any;
}
// store.mappers.ts
import { makePickable } from './pickable'
import store from './store'
export const mapDirectGetters = makePickable(store.getters);
export const mapDirectMutations = makePickable(store.commit);
export const mapDirectActions = makePickable(store.dispatch);
~Right now you have to import store and pass it as the first parameter~ (and getters have to be spread into data, not computed for the types to work), but I guess it's a good start.
Edit: I solved the issue of having to pass store as the first parameter. Now I just need to somehow make getters behave correctly, which I don't know how to do. But I think if we combined this with the internals of direct-vuex
, we could create the mappers directly when in createDirectStore
Are there any plans to add typed variants of these helper functions? I might give it a try myself but I don't know if something like that is possible with the current implementation. I guess you could pass the store as a parameter to extract the types?
something like:
I'd like to hear your thoughts on this.
EDIT: I mean, we can just return the
mapDirectGetters
fromcreateDirectStore
so we don't have to pass this.$storeso it would be:
and then