Closed markwhitfeld closed 7 years ago
This finna be a nightmare.
It looks like createArraySelector
and createObjectSelector
are trivial, albeit with some obnoxious codegen. Making the more generic createListSelector
and createMapSelector
work perfectly seems impossible without higher kinded types. The input collection could be done since the it just needs to adhere to an interface, but you'd have to manually write out the selector's result type. That's annoying but not necessarily a deal breaker. Maybe we could do something with default parameters to make it work decent out of the box. Thinking out loud...
Just off the cuff, the first two look roughly like this.
function createArraySelector<S, E, RN, T>(
arraySelector: Selector<S, E[]>,
selectorN: Selector<S, RN>,
combiner: (elem: E, resN: RN) => T,
): Selector<S, T[]>
function createObjectSelector<S, E, RN, T>(
objectSelector: Selector<S, { [string]: E }>,
selectorN: Selector<S, RN>,
combiner: (elem: E, resN: RN, key: string) => T,
): Selector<S, { [string]: T }>
I'm kinda convinced that the other two aren't possible, but someone smarter than me can take a crack at it.
That looks about right. As I mentioned above they would probably look very similar to the ones from the "reselect" module. I was going to try to do it myself and submit a pull request but I ran out of time today. I'll let you know if I start working on it. My next chance will probably be in a week's time.
I'm not sure if it works or what else needs to happen for it to be packaged up, but here is what I've done so far. Some good old fashioned string-based code generation. Anyone interested in getting type definitions added should try it out and let me know!
I tried it out and it works perfectly except for one small issue that an object map can be keyed on either a string or a number. I will submit a pull request shortly. The object selectors make use of a union type to support both string and number keyed values. eg:
type ObjectMap<T> = { [key: string]: T; } | { [key: number]: T; };
export function createObjectSelector<S, E, T>(
selector1: Selector<S, ObjectMap<E>>,
combiner: (elem: E, key: string) => T,
): OutputSelector<S, ObjectMap<T>, (elem: E, key: string) => T>;
// etc...
Thanks!
I am using your library from a typescript project.
Please could you add a typing definition to the project so that it can be used in a type safe way. Have a look at the 'reselect' module because they have done it there and your module is very similar.
Thanks!