Personally, I find direct Typescript interpretation to be one of the best features. Typescript is not necessarily a simple type system, but it is an expressive one:
- It has great type inference avoiding Java style codespam
- It has gradual typing, enabling "risky" type casts
- It has fully functional types, enabling the productivity and readability improvements from functions as data
- It is 10 seconds away from having dependent types
Typescript took most of the best programming language research from the past 20 years and popularized it in a way that actually makes js hackers more productive without getting too much in the way.
The only hard thing has been that js interpreters don't understand typescript, requiring an awkward transpilation step with weird symlinks and other hidden complexity that works 99% of the time, but wastes a lot of time when it doesn't work just right.
If Deno could just solve that, it would be a great improvement. If it's also faster (as claimed) that's even better. This article shows a lot of other ways in which small, simple improvements add up to a much better product.
Can't wait until it's production ready.
If you don’t need systems language type performance, and don’t need true parallelism, it’s a pretty terrific choice. Starts out productive/simple in the early days of a project, stays productive/simple as it grows. Plus, if you’re doing “mobile apps + web app + RESTful services”, pretty nice that you can do it all in one language (assuming React Native on mobile), and that there’s no JSON related boilerplate.
A lot less would be a lot more, because as of now Typescript lures otherwise entirely competent programmers into writing complex 'type system puzzles' which are entirely obscure to everybody except the person who wrote that code, and it takes a lot of discipline and experience to reist the lure and keep things simple.
I want a type system that embraces the correct way to to do things instead of allowing anything you want no matter how bad it actually is. I want my type system to inform me that my code is really bad for performance and should be redone.
Instead, I constantly deal with people who think their code is fine just because the TS checker doesn't complain.
Excessive typing is very costly and should be left to popular libraries that solve generic problems. This is where you get best bang for buck.
It should not be present in your business code, high level business logic is rarely prone to type errors anyway.
Static typing was always a means to an end, but unfortunately it was recently sold as a virtue and many people have bought it.
They are the most natural way to encode structural information, especially across language/system boundaries.
- Clojure’s multimethods (multiple dispatch)
- Clojure spec’s “or”
- JSON schema’s “anyOf”
There’s likely more features and tools that are not strictly/statically discriminated/tagged unions, but in practice they help you to code that way.
In TS this is IMO the best feature. In a sense it just adds tooling support on top of a coding style that is very close to dynamic typing.
- It uses the v8 engine so you've got the same APIs you know and love for the browser like fetch() - Something that nodejs is just catching up to now
- It's not nodejs, the whole name means 'destroy node'. You can get a lot done without being buried in dependencies. Well-maintained core libraries.
- Server-Side WASM is a really interesting idea for encapsulating and integrating stuff written in, say, C++
The cons:
- Some of the third party ecosystem seems to be suffering from a lack of recent maintenance
- Server-side WASM is limited to 32-bit until they figure that out, which also limits whatever you do with it to a 4GB memory ceiling
Other than all that though it's probably not a bad choice for anyone not bothered by those limitations and just wants everyone who speaks typescript on the frontend to be able to grasp what's on the server side end of things too.
I think it could probably thrive with more usage traction.
Server-side WASM is the future for FaaS imo, sandboxing built in and an effective object-capability approach to dependency safety is amazing.
Deno doesn't mean 'destroy node', it's just node reordered.
How's the performance vs ffi version? I'm about to use deno with sqlite and have to decide which one to use. The lack of WAL in WASM version gives me a pause though.
The limitations that stick out most to me personally are that there's still no ARM support, and that, while the Node compat is getting a lot better, it's still hard to get a clear sense of where it is for individual packages -- what runs natively/is isomorphic, vs what'll run under a compat layer, vs what just won't run at all.
Ooft. Although TypeScript does have a bit of a learning curve, and a lot of gotchas, I still have to say it's my favorite language to use. If you combine the delicious syntax-sugar of ES6 (and beyond) with a sprinkling of tasteful types, the language leaves you full and energized without feeling bloated.
I’m not that into class-based languages and prefer a language to have macros (more for DSLs they enable them for application code). However, even if those preferences were off the table, I’d still rather have something like Kotlin on the server than TS. It’s simpler and isn’t weighed down by 30 years of cruft.
It's a language that supports both function and OO paradigms.
Also, if macros/DSLs are what you're after, then you'd probably be interested in typescript's decorators. (you can use the old experimental decorators based on the old standard from ages past, and the new *standard* decorators introduced in typescript 5 which are based on the current stage-3 ecmascript proposal).
The only things typescript as a language is really lacking are:
1. Pattern matching (minor issue)
- +90% of pattern matching is really just a more concise switch/case syntax
- the remaining -10% can be done by hand with mapping or just basic if statements
2. Immutable data-structures (minor issue)
- The `as const` suffix handles most of the use cases.
- There is a Records/Tuples proposal which would give some better syntactic sugar and some run-time performance improvements too.
3. Trait system (minor issue)
- Typescript compiles down to Javascript which at the lowest level is actually a prototype-based language. Traits can be approximated using run-time mixins which alter the prototypes to essentially perform the same functions as traits.
- But, it would be nice to have compile-time rather than run-time support for traits.
- I think most languages are still only coming to terms with the fact that traits are often better than "traditional OOP classes".
4. Effects system (investigate)
- It's too early to tell, but having an effects system (à la OCAML 5) will probably lead to entirely new programming paradigms. I'm not sure where it will lead, but having native algebraic effects to replace try/catch/throw would be very nice.
Edit: Formatting
Otherwise I have to agree, Typescript is a pretty damned good compromise.
When people say typescript is hard to learn, do they know javascript, or are they starting from scratch?
I don't think you need to use most of these types until you start getting into stuff like needing union types. You can get away with reading and writing most typescript without getting too crazy.
I think the most compelling thing I read about type hinting is that it's like salt - A little and the dish doesn't taste the same without it but too much and you've ruined the thing
Python's type hints and Ruby's Sorbet (or their weird RBS thing), I can understand.
But TypeScript? Besides a few things that are not obvious at first (like callable interfaces), I don't think you really need to think about most stuff.
> Additionally Invo supports USD, EUR, JPY and GDP currencies.
Did you mean `GBP` here?
One usability issue - the currency selector is hidden behind a gear icon on the last Total line, whereas you see the currency in previous lines without the ability to change it. I would move it somewhere much more obvious.
["10","10","10"].map(parseInt)
?You have to do `['10', '10', '10'].map((val) => parseInt(val, 10));` to get the "expected" output. In addition, you should always provide `base` to `parseInt` otherwise it has it's own interpretation infered by the value you give it.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
['10', '10', '10'].map(val => parseInt(val))
Leading zeroes can often be considered invalid input, and you may be able to safely assume that it has been dealt with already.Also the parens around a single argument of an arrow function are a superstitious thing suggested by some well-known react developer a while back, I think.
You can try ["10","10","10"].map(console.log) for more info... the third argument is the source array:
> 10 0 ['10', '10', '10']
> 10 1 ['10', '10', '10']
> 10 2 ['10', '10', '10']Click the 'Run' button:
https://www.typescriptlang.org/play?#code/MYewdgziA2CmB00QHM...
But yeah it is just a case of the map providing 3 args to the function (element, index, array) and parseInt using 2 value s (string, radix) so we have element->string (yay!) and index->radix (oof!) and array->ignored (meh!)
`Array.map` function API was badly designed. I'd like to know who I should to blame for that design.
Ryan Dahl was there as well as a junior engineer (L4).
L4 typically are engineers who graduated for 1-2 years.
Meanwhile Ryan has built a programming engine that has been used worldwide and widely popular on the same scale of Ruby, Java, Python... But he was slotted as an L4.
Here's some context on that from Ryan: https://tinyclouds.org/residency
It does not sound like a typical Google software engineer position or one where leveling is particularly significant.
As an extreme example, a best brain surgeon or businessman in the world would completely fail Google's software interview and be rejected.
A new grad joining Google for 2 years would likely reach L4.
Just for the record, Deno does allow finer grained control than that:
> --allow-net=<allow-net> Allow network access. You can specify an optional, comma-separated list of IP addresses or hostnames (optionally with ports) to provide an allow-list of allowed network addresses.
First class capabilities are a much better approach, a real solution to supply chain attacks.
Though most people will likely just --allow-all because it is easy.
Deno sounds well thought out, but the article realistically presented no compelling reason to try it.
And realistically, it presented many reasons not to. Javascript is a horrendous language. Not because of the syntax, not because of the library support, but simply because even self-dubbed javascript 'experts' are often confuddled by its standardized behavior. We could probably count on several fingers the number of people who can accurately describe javascript's semantics. As the rest of the computing world moves towards sane languages, this seems like backwards 'progress'.
One of the good points about deno raised in the article is that deno removes that problem by having first-party solutions to things that developers usually need built-in.
Also while JS has plenty of footguns, Deno being built around TS and deno ts developers using eslint as a standard practice eliminates those footguns.
Jest and Mocha both do not support ESM very well out of the box and there is an expectation that you are using babel to transpile to CommonJS for everything to work nicely. (See Jest's _experimental_ support for ESM mocking!). Node.js is only starting to build out a testing framework, and it has a way to go yet until it has any level of feature parity with the established libraries.
Then you have the naive assumption that any package written in JS works with TS. Which is true, they do work, but the missing types will always lead you to look for a TS-first alternative. A good example of this is Joi vs Zod for validation, with the latter performing type inference based on your validation parameters, which is great. But it really does feel like you have a subset of a package ecoystem lurking on NPM.
I am not that confident Deno is the answer, but I would say those are my biggest frustration writing production grade JS/TS code today.
The Node testing ecosystem has its obvious advantages in terms of how much it’s been buttressed by third-party efforts (which makes it incredibly flexible), but just being able to write a TypeScript test file, run `deno test` and just have it work is really a breath of fresh air.
tsx is a CLI command (alternative to node) for seamlessly running TypeScript & ESM, in both commonjs & module package types.
It's powered by esbuild so it's insanely fast.
I also suggest using its alias: esno
https://github.com/denoland/deno/issues/14244
You have to use a third-party Docker container if you want to use Docker locally and develop on an M1 Mac (I use Docker to separate my different dev environments). And the issue was just ignored and became stale.
I'm assuming you've never run into node-gyp issues then?
You still see this frequently in a number of ecosystems (eg https://stackoverflow.com/questions/70061068/could-not-find-...)
Regardless, my experience on the platforms it works on has been very positive.
We have a hub [2], centered around deno, that serves as our library of integration. An integration for us, is just a script that uses the right dependency to do an atomic action like fetching data or doing a POST.
We are betting big on deno, and are hoping with windmill to be the framework to make it enterprise-ready for other things than webservers (which most of the deno framework currently focus on).
[1]: https://github.com/windmill-labs/windmill [2]: https://hub.windmill.dev
Also, starting with an empty workspace and importing examples from the hub manually might be less confusing. With public workspace having all these examples, "Home" is cluttered and it's not obvious that new scripts also end up there.
Overall it's very impressive, thanks for open sourcing!
[ 10, NaN, 2 ]
what... the... fuck...
I have seen the WAT video but forgot about this example.
The biggest thing holding back TypeScript is the awkward transpilation dance, a weak standard library in Node and relatively poor performance - none of which are the fault of the language.
Break free TypeScript, you gotta move out of your parents' place eventually
But it goes into a slightly different direction from what you want (the main motivation was a "stripped down TS for WASM", not a "stripped down TS with go routines"). It will be interesting to see how they'll tackle multithreading (now that WASM threading is out in the wild).
My two main quibbles about Deno are:
1. The rather pointless security model that seems about as relevant as it did for PowerShell.
2. It's quite young, there's still some pointy edges.
["10", "10", "10"].map(parseInt)
is the sanest. Taken in isolation, the parameters of both Array.prototype.map and parseInt makes sense, and a typed language wouldn't help there too much. All hope is on ESLint rules to not let you do shortcuts which could burn you.
That would be impossible in a typed language. The argument of map() is supposed to be a function with signature (T, Integer, T[]) -> R and parseInt() has signature (String, Integer) -> Integer.
On the contrary. Ryan Dahl, the person who created node, came up with deno, specifically to address a number of problems (or regrets) he had with node: see https://youtu.be/M3BM9TB-8yA.
For example, what is the problem with calling the TypeScript compiler? I have a build setup anyway, so why does it need to be integrated? That's an example of a solution where I don't see the problem.
But a lot of people think that multiple implementations and specs are good things (I personally don't know which way I go on this one). And thinking about it, I kind of don't buy the argument. There are specs for JavaScript and TypeScript, and multiple standalone JS and TS engines: node, QuickJS, duckjs, Bun, etc.
I also don't buy the "minimal, practical" take on dependency management. It sounds like they just built a package manager into Deno itself and put versions in the URL, which feels like the opposite of minimal and more like "batteries included". Again not saying this is bad--the Python ecosystem suffers pretty badly from not having their dependency story totally mapped out--just quibbling over the characterization.
On the other hand, I do buy the security thing. AFAIK this is the first scripting runtime to essentially integrate pledge [0], which is real interesting.
In the case of dependency management, they use a pattern which would also work for client code shipped to a web browser (in that case the client would assemble the code - like if you had a reference to load mathjax or google analytics or whatever, or you could alternatively vendor and ship them yourself).
To me Deno is basically modern web standards + very nice tooling for use as a scripting or serverside language (typescript interpretter, format, compile, vendor, test, lockfiles/import maps, ability to explicitly include/exclude capabilties from runtime, etc).
Usually when I do anything in the node/npm world I have to steel myself. But Deno & Deno deploy are actually fun.
While this is certainly nice, should third-party code be actually committed in your version control system? I always treated it like a bad idea. Adding node_modules to gitignore is second nature now.
The present: Use an enormous, complex, sometimes closed source, omnibus program containing a Javascript engine to remotely source and run Javascript files, i.e., other peoples' programs, listed in webpages (sometimes cascades of them as dependencies) in a way that is non-transparent to the user, allowing selected access to certain features of the the user's computer, all mediated and controlled by Big Tech with its dependence on advertising and associated data collection and surveilllance and conflict of interest with respect to users.
The future: Use a standalone Javascript engine to remotely source and run other peoples' Javascript programs in a way that is transparent to the end-user, with all access to the user's computer, if any, under the full control of the user, with no dependence on advertising and no need for data collection and surveillance.
"Javascript" might be replaced with some other language. Typescript, WASM, whatever. In the earlier days of the web before Javascript, people tried to use "Java applets". Back in those days when an applet was encountered the browser would ask the user for permission to run it. As I remember it, this was about as annoying as cookie permission popups, another idea that was implemented in the earlier web then disappeared, but has now been re-implemented due to emrging privacy laws.
However, the security issues are valid but not necessarily an issue solved by the framework. Ultimately some kind of package manager that had a manual review step before packages could go out would be a nice step, and would work at scale as well.
Manually listing permissions for an application works for security until people get tired, or are just so used to saying yes. Its also very bold of deno to assume their sandbox is impossible to escape. It’s much more likely that no one cares to really try.
What is injection-proof template literal? Any link about that? Thanks :)
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe... for specific implementation in JS. Compare with f-strings in Python, which are superficially similar, but can’t be used to, eg, construct SQL or HTML not prone to injection attacks.
Also I think this whole granular access thing is weird. I never wanted it, container isolation is more than enough. Hopefully it does not add much drag to deno progress.
I think the win with Deno is the JS ecosystem and the situations where JSs dynamicity is an advantage. Sometimes (often times, in my own estimates) that's worth double the memory usage and 20% the raw CPU performance.
In my experience, however, as soon as my tasks section got large enough that a separate file was needed, it became long-running enough that I wanted a generic file dependency-aware builds which required a make-like solution. What should large projects do that need to build assets or perform long-running work as part of a build process without dipping into another clunky tool?
I have similar issues with threading development-only import maps that reference local modules in a polyrepo during development and sharing common Deno configs. Customization doesn't scale well to task one-liners even though I want it to. Do folks know of open-source polyrepo reference that serve as a paradigm for patterns that scale?
The good old Unix philosophy of designing simple tools that are doing only one thing right has proven extremely useful in the context of using the Shell as a scripting interface.
Composability is paramount to be able to glue small cogs together to quickly build a larger machine for ones needs.
But this way of thinking should not apply to everything, especially not when the tool itself is designed to be used a direct interface with the user (like a Shell).
I would really appreciate if deno-task-shell could be used in a shebang for writing scripts that expands on several lines in dedicated files.
I laughed a little when I saw the author hinting at TS creating complex structures. A reason I never adopted it. A great use of TS would be to type the external interfaces though!