What can TypeScript learn from Zig? What can Zig learn from TypeScript?
effectivetypescript.comOn the author’s point of a “debug build” with runtime type checking, there is ts-runtime-checks [0], which looks to do something similar! I don’t have any experience with it however, just seen it looking at typescript-runtime-type-benchmarks [1]. There’s a few other similar things there too
[0] https://github.com/GoogleFeud/ts-runtime-checks
[1] https://github.com/moltar/typescript-runtime-type-benchmarks
Thanks for the pointer, I hadn't run across ts-runtime-checks before. It does do something similar to what I propose in the post. The difference is that ts-runtime-checks is opt-in. If you want a type validated at runtime, you have to write `Assert<T>`. What I'm proposing is that _all_ types be validated at runtime.
opt-in makes sense if you want these checks in production. The appeal of a "check everything" debug mode is that you wouldn't have to modify your TS at all to use it.
There's io-ts, a library built specifically for this, and it's based on the basis of famous fp-ts
Out of curiosity, how long is your experience with TypeScript? I feel like I have to ask.
>TypeScript does not modify this code when it compiles to JavaScript
TypeScript does not modify any code which is valid JavaScript. Your idea of adding some sort of "debug build" to TypeScript would never be performed by `tsc`, but perhaps by bundlers, etc.
You might want to look up libraries like zod, or even better, Effect: https://effect.website/
Extensive. Try reading the full post, you'll see that those points are all mentioned.
Ive used fp-ts, mainly for Either, Option, and Pipe. I tried out Effect for a new project, and have loved it. The initial hurdle was a little intimidating but I was productive with it within 2 days, and it's paid dividends. It's discord community was surprisingly great, and helped me turn an okay module into an amazing one.
Effect is huge, and does seemingly everything, but it probably does the specific thing you want to do now, with the ability to extend to the other stuff as you need/want
Typescript's refusal to participate in codegen is one of the things I don't like about it.
It makes Typescript a descriptive, rather than expressive, language with weak semantics.
I don't come from TS, but this seems like a good intro to zig from that sort of perspective. There's a whole lot of paradigms to relearn when you switch to something like Zig and this kind of content is useful.
I'll nitpick with one complaint though...
const values = std.AutoHashMap(Point, u32);
defer values.deinit();
try values.put(Point{ .x = 0, .y = 0 }, 1);
// ~~~~~~^~~~ error: expected 3 argument(s), found 2
> The mistake here isn't on that line, and it doesn't have to do with the number of arguments. Rather, it's that I forgot to call .init() on the hash mapWell...
>>> class MyType():
... def test(self, a, b): return a + b;
...
>>> x = MyType
>>> x.test(1, 2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: test() missing 1 required positional argument: 'b'
How else do you want unbound functions to behave when you haven't constructed an instance of the type yet? (And FWIW, zls in vscode correctly annotates values as having type `type` for me)If the type is `type`, and you're missing one argument, and the types of the arguments suggest you're missing the first argument, then that's an opportunity for a much more specific error message.
But before we even get to that stage, I would prefer that "." isn't the syntax for both types of call.
Agreed on both counts. We give C++ a lot of flack for verbose syntax, but separating scope resolution (::) from member access (.) is something that it got right, not a place to cut.
They're semantically similar, but not the same, which is actually exactly the place where you should distinguish syntax. Using parentheses for both expression grouping and function calls doesn't hurt readability much, but using them for both function calls and array access would. This falls more in the latter category.
Yuck. The type itself should be a different type from instances of the type, and therefore that error should be "function not found".
For the first one, constructors should generally do required init, although there are circumstances where that's very hard. Hence the builder pattern.
This is a common pattern in zig and compliments comptime well. It's not supposed to be the constructor for the ArrayList, it's more like a C++ template in that you're constructing a type that then needs to be initialized. There isn't templating syntax in zig though, since you just write compile time code in zig directly (which is really nice).
Also, the type is different and ZLS will insert the hint if enabled.
Yes, the error is much clearer when you realize where the mistake is :)
There's an interesting point here, though: while comptime lets Zig unify function calls and generic type instantiation, this also creates the possibility of confusing the two and getting confusing error messages.
I'm surprised that the list of Zig quirks doesn't include aliasing and functions parameters: the compiler can pass your parameter by value or by reference as it wants so your function behaviour can change in case of aliasing..
An implementation defined behaviour worse than C, that's surprising..
Ada has the same issue, I wonder if Ada users can tell us if this pitfall is an issue or not in practice.
Since function parameters are immutable in Zig, is this a difference that you need to care about?
The parameter is immutable so if you pass a pointer, the pointer is immutable, but the pointed value isn't.. If the pointer alias another 'immutable' parameter, this parameter may not be immutable anymore..
Another language that we can build type with its own language is Python. The problem is that there is no checker for that kind of type, however :)
Never use Mypy, but I think it probably check only the static-like (with generic) types like any other static languages.
Using shedskin Python to C++ compiler is a kind of roundabout way of doing that. :)