The Good

Native TypeScript support

Yep, you can create a .ts file and run it out of the box with deno run file.ts. You don't need a tsconfig file and you don't need to transpile it to JavaScript first.

Built-in formatter

Deno ships with a built-in command to format your code: deno fmt. You can run this in your project root, or pass it a list of filenames, and the files will be formatted to a consistent standard.

I can remember when I was learning Go. I created a file in VS Code, hit Save, and when I did, the file transformed before my eyes: an invisible force adding spaces to struct type definitions. I didn't like it at first, but now it is one of my favourite features. Not having to consider and maintain a .prettierrc file is a definite win in my book: the less competing code "style guides", the better.

Top level await

This is a feature that is very likely to arrive in Node soon: being able to await a function at the top level. Previously, you'd need to wrap the await in an IIFE (immediately invoked function expression), if you wanted to use await at the top level:

(async () => {
    await something();
})();

In Deno, you can simply:

await something();

Secure by default

A really great feature in Deno is that a lot of functionality is locked down by default. Access to the filesystem, system environment and network access is opt-in via flags when running a program. These flags aren't boolean either: you can pass in a comma separated list of values to allow.

For example, this will allow the cat program to read anything off of your filesystem:

deno run --allow-read cat.ts

This will only allow Deno to connect to https://tomm.us:

deno run --allow-net=https://tomm.us scrape.ts https://tomm.us

The Bad

No package.json scripts

This isn't a bad point in itself. The package.json file has grown to contain a crazy amount of information.

One of the sections that I miss in Deno is scripts. This allowed you to define scripts that you could run inside the project using npm run .... For example, you could lint with npm run lint or serve your website with npm run serve.

This is not possible in Deno, because it doesn't have (or need) a package.json file. I'm sure that standards will become established, but currently it looks like a toss up between a Makefile, bash scripts, or the interesting Drake package.

NPM Incompatibility

Deno doesn't support npm packages. There's no two ways about this—this is currently a big negative for me. There are efforts out there to automatically convert some packages to be consumed by Deno, but any package that uses APIs from the Node runtime will need at least some effort to be compatible. This is any package that uses process.env, imports the Node fs module, etc.

The Ugly?

Imports

Because Deno doesn't use npm, you don't import packages using import { name } from "package-name";. Instead, you use a full URL to the package:

import { name } from "https://github.com/tmus/package/raw/master/name.ts";

This looks weird at first, but it makes it really clear where a package is coming from. Because this is a URL, this has the added benefit of being able to be cached globally by Deno—if you import this package in one project, and then go and import it in another project, Deno already has it downloaded and cached, meaning a quicker install time for your third-party packages.

Initial kneejerk reactions are how do you know that the file won't change? and that's gonna be a nightmare to import into the top of all my files!

How do you know that the file won't change?

You can create a lockfile to check the integrity of the contents to ensure that the file remains unchanged.

That's gonna be a nightmare to import into the top of all my files!

Nope! Deno docs suggest that you create a deps.ts file in the root of your project, and import and export all third-party packages there, you can then import them from your deps.ts:

export { name } from "https://github.com/tmus/package/raw/master/name.ts";
deps.ts, using the one-line export synax defined in ES2020.
import { name } from "./deps.ts";

console.log(`Hello, ${name}!`);
Importing name from deps.ts

That about does it; if you've played with Deno, and agree or disagree with any of the points above, or think I've missed out some glaring features, reach out to me on Twitter!