JS for Go Devs

beyondcodebootcamp.github.io/presos/js-for-go-devs/


Dependency Management


Go: 10 Years
(2009 - 2019)

(but perfect)


JavaScript: 30 Years
(1995 - 2025)

(and is... workable)

git.rootprojects.org/root/walk.js/issues/1


JavaScript


a fundamentally good language
with a fundamentally bad community.


Gopher Values


Browser JS: Module Declaration

go.mod => index.html

index.html

<script type="importmap">
  {
    "imports": {
      "@root/passkey": "./passkey.js",
      "@root/passkey/": "./lib/",
      "localstore": "./vendor/localstore.js"
    }
  }
</script>

JS: Export Module

(one file of a Package)


// filename: ./passkey.js

let Passkey = {};

// ...

export default Passkey;

❌ (the other 12 ways)


JS: Import Module

import Passkey from "@root/passkey";

(the other 12 ways)


Node JS: Module Declaration

go.mod => package.json

{
  "name": "@root/passkey",
  "main": "./passkey.js",
  "type": "module",
  "exports": {
    ".": "./passkey.js",
    "./*": "./*"
  },
  "imports": {
    "@root/passkey": "./passkey.js",
    "@root/passkey/": "./lib/",
    "localstore": "./vendor/localstore.js"
  },
  "dependencies": {
    "foo": "1.0.0"
  }
}

JS Type Linter: Module Declaration

TSC's go.mod => jsconfig.json

{
  "compilerOptions": {
    "paths": {
      "passkey": ["./passkey.js"],
      "passkey/*": ["./lib/*"],
      "localstore": ["./vendor/localstore.js"]
    }
  }
}

Types

(are in the Tooling)

// init jsconfig.json that works
npx jswt init

JS Types

(they exist)


let person = {
  name: "AJ",
  age: 38,
};

/**
 * @typedef Person
 * @prop {String} name
 * @prop {Number} age
 */

/** @type {Person} */
let person = {
  name: "AJ",
  age: 38,
};

/**
 * @param {Object} opts
 * @param {String} opts.name
 * @param {Number} [opts.age]
 * @param {Person?} [opts.partner]
 */
function createPerson(opts) {
  let person = {};
  person.name = opts.name;
  person.age = opts.age;

  // ...

  return person;
}

/**
 * @callback {CreatePerson}
 * @param {Partial<Person>} opts
 */

Utility Types

/**
 * @param {Partial<Person>}
 * @returns {Required<Person> & SoulMater}
 */
function complete(person) {
  let defaults = {
    name: "Unknown",
    age: -1,
    partner: null,
  };
  Object.assign(defaults, person);
  return person;
}

JavaScript Types, Actually

/** @typedef {Number} Int32 */
/** @typedef {Number} UInt32 */ // ex: -1 >>> 0
/** @typedef {Number} Int53 */
/** @typedef {Number} Float64 */

Go: Explicit Ignore

func greet() string {
  return "Hello, World!";
}
_ = greet()

JS: Explicit Ignore

function greet() {
  return "Hello, World!";
}
void greet();

- void greet();
+ void greet()

Go: Defer

func doFileStuff(path) {
  f := os.Open(path);

  defer func () {
    f.Close()
  }()

  // ...
}

JavaScript: Defer

function doFileStuff(path) {
  try {
    let f = Fs.open(path);

    // ...
  } finally {
    f.close();
  }
}

(better to have a new function than to nest)