#Declarative programming: functions / types design question

10 messages · Page 1 of 1 (latest)

spice night
#

Greetings TS community.
I've got into declarative programming with Typescript and I'm trying to design my code and types more in this style, however I run into a road bump which is giving me a headaches.

I'm working on a complex function, but for the sake of everyones attention span, I've cut it down to the problematic part.

(Typescript playground link in the comment)

The question is how does my internal function know which keys are selected on top level so it can create a proper signature of the return value.
This might be a perspective issue, rather then a TS issue per say, but hopefully someone can put me on the correct path.
Cheers

lost lichenBOT
#
orahkokos#0

Preview:ts // Utility const pick = <T extends Record<string, unknown>, K extends keyof T>( obj: T, keys: K[] ): Pick<T, K> => { const result: Partial<T> = {} keys.forEach((key) => { if (key in obj) { result[key] = obj[key] } }) return result as Pick<T, K> ...

slate violet
#

is there a reason you are defining your flow utility yourself, rather than using one from an existing library that supports this pattern?

spice night
#

Greetings @slate violet . This is a module which I am writing with 0 dependencies. Beside the nature of the requirement, it is also a challenge to try and do it correctly.
I think the name of "flow" might be misleading in my case. Imagine this function is called "internalProcessFunction" instead of "flow".
The challenge stays the same: How do you have "SomeData" as initial type and then accept a function which will take subset of that type, using a curry function on top level where you specify keys ""withNested1"

twilit zodiac
#

TypeScript doesn't support partial type parameter specification, so your definition of flow won't quite work... if you add one dummy function on top, inference can take you the rest of the way there though

lost lichenBOT
#
gerrit0#0

Preview:```ts
...
interface Flow<I, O> {
<T>(fn: (data: I) => T): Flow<I, O & T>
(data: I): O
}

declare function flow<T>(): Flow<T, {}>
...```

twilit zodiac
#

(FWIW I'd likely strongly dislike dealing with this code if I ran into it in the wild somewhere, this style of programming tends to go wildly out of control very quickly in my experience)

spice night
#

@twilit zodiac Ah thank you so much for the pointer + example! The keywords are "Partial Type Argument Inference". I've found the github issue discussing this feature: https://github.com/microsoft/TypeScript/issues/26242
Your opinion on the code is understandable, I assure you its just 1 function in the entire code base 🙂 . If it was anything more then that I'd probably pivot towards effect-ts or to some more appropriate FP lang.

I find that declarative programming is a really good brain exercise and it makes me rethink how i design my code.

GitHub

After exploring the concept in #23696, we've come to the conclusion that implicitly making type arguments available by name would unnecessarily expose previously unobservable implementation det...