Live data from Hacker News

Make any TypeScript function durable

useworkflow.dev

61–70 of 89 posts

Re: Make any TypeScript function durable

#61

i hate the new pattern of using these magic strings everywhere. “use workflow”, “use client”, etc etc. I don’t like having custom bundler logic for my code.

"don't use next" "don't use react"

Please, bundling React with Next is completely foolish. React is open, battle-hardened, type safe, and well-documented, while Next is... a vendor lock-in trojan horse targeting low-knowledge developers with concepts that seem beginner-friendly.

I can understand making legit criticisms of React, no doubt the hooks transition had some issues and the library has a high level of complexity without a clear winner in the state management domain, but pretending React is peddling shit like "use workflow" is frankly low effort.

Re: Make any TypeScript function durable

#63
> For instance, Math.random and Date constructors are fixed in workflow runs, so you are safe to use them and the framework ensures that the values don't change across replays.

How do you create an environment where everything is deterministic? Do they invoke every supported non deterministic function when creating the environment and rewrite those functions to return the values from the environment's creation time? Is there something more complex happening?

Re: Make any TypeScript function durable

#64
post #61

Earlier quoted context omitted.

"don't use next" "don't use react"

Please, bundling React with Next is completely foolish. React is open, battle-hardened, type safe, and well-documented, while Next is... a vendor lock-in trojan horse targeting low-knowledge developers with concepts that seem beginner-friendly. I can understand making legit criticisms of React, no doubt the hooks transition had some issues and the library has a high level of complexity without a clear winner in the s…

Just shows you how absolutely little people know about the web ecosystem - most people heard something once or twice from someone else and just assume its true - to make matters worse, you have the typical HN "vanilla html and js only!!!" bandwagon which, if you try to use for any serious web application will only lead you down a path of much pain and suffering. I've commented many times in many other threads that I just don't get it; I probably never will.

Re: Make any TypeScript function durable

#67
post #30

Earlier quoted context omitted.

But then it's not valid TypeScript anymore. So all the other tooling breaks: syntax highlighting, LSP, Linter, ...

Looking at the AST [0], this doesn't seem to be the case. Since Typescript already supports decorators in other contexts, it successfully parses everything and identifies the decorator to boot. Since you're working in a preprocessor context anyway, there's a number of options to make all of this work well together. [0] https://ts-ast-viewer.com/#code/GYVwdgxgLglg9mABMOcAUBKRBvAU...

But you can see there that it flags it as an error. The parser is lenient, sure, and tries to parse the rest of the file despite the error, but it's still not valid syntax, so you'd need to update all your other tools (LSP, formatter, linter, etc) to understand the new syntax.

Re: Make any TypeScript function durable

#68

Earlier quoted context omitted.

Looking at the AST [0], this doesn't seem to be the case. Since Typescript already supports decorators in other contexts, it successfully parses everything and identifies the decorator to boot. Since you're working in a preprocessor context anyway, there's a number of options to make all of this work well together. [0] https://ts-ast-viewer.com/#code/GYVwdgxgLglg9mABMOcAUBKRBvAU...

Instead of decorators, it could be just a higher-order function. Which could handle it easily and in any scenario that interchanges between TS/JS.

The problem with higher-order functions is that you can't guarantee that your static analysis is correct, and you end up with functions that look like functions but don't behave like functions.

It's similar to the problem that `require` had in browsers, and the reason that the `import` syntax was chosen instead. In NodeJS. `require` is just a normal function, so I can do anything with it that I could do with a normal function, like reassigning it or wrapping it or overwriting it or whatever. But in browsers (and in bundlers), all imports need to be statically known before executing the program, so we need to search for all calls to `require` statically. This doesn't work in JavaScript - there are just too many ways to dynamically call a function with arguments that are unknown at runtime or in such a way that the calling code is obscured.

That's why the `import` syntax was introduced as an alternative to `require` that had rules that made it statically analysable.

You'd end up with a similar situation here. You want to know statically which functions are being decorated, but JavaScript is a deeply dynamic language. So either you end up having a magic macro-like function that can only be called in certain places and gets transpiled out of the code so it doesn't appear at runtime, or you have a real function but you recognise that you won't be able to statically find all uses of that function and will need to set down certain rules about what uses can do with that function.

Either way, you're going to be doing some magic metaprogramming that the developer needs to be aware of. The benefit of the "use X" syntax is that it looks more magical, and therefore better indicates to the reader that magic is happening in this place. Although I agree that it's not my personal preference.

Re: Make any TypeScript function durable

#69
post #14

Earlier quoted context omitted.

Decorators don't work for functions, unfortunately, so wouldn't work in this case. You'd need to add a bunch of class boilerplate to make it work. JavaScript didn't have a lot of great options for this kind of statically-declared metaprogramming, which is why the "use X"; syntax has become so popular in various spaces. It's definitely not my favourite approach, but I don't think there's any clear "best" solution here…

You can use generator fns to achieve the exact same thing without magic strings or bundles. And the bonus is that you can debug it.

I don't believe you can. I believe what they're trying to do is rewrite the underlying function into separate functions that can be called in any order and combination. That's not possible with generators. With a generator, I can pause between steps, but I can't, say, retry the third step four times until it succeeds, suspend the entire process, and then jump straight to the fourth step. Or I can't run different steps in different processes on different machines depending on load balancing concerns.

I suspect that's why they need to transform the function into individual step functions, and for that they need to do static analysis. And if they're doing static analysis, then all the concerns detailed here and elsewhere apply and you're basically just picking your favourite of a bunch of syntaxes with different tradeoffs. I don't like magic strings, but at least they clearly indicate that magic is happening, which is useful for the developer reading the code.

Re: Make any TypeScript function durable

#70
post #69

Earlier quoted context omitted.

You can use generator fns to achieve the exact same thing without magic strings or bundles. And the bonus is that you can debug it.

I don't believe you can. I believe what they're trying to do is rewrite the underlying function into separate functions that can be called in any order and combination. That's not possible with generators. With a generator, I can pause between steps, but I can't, say, retry the third step four times until it succeeds, suspend the entire process, and then jump straight to the fourth step. Or I can't run different step…

You are partly correct, if each step is another generator function you can retry the steps until success or fail, and even create a small framework around it.
Post reply on HN