• Data Structures in TypeScript

    Took some time off this weekend to learn some TypeScript, and reimplemented some data structures as practice.

    I don’t think I’ll continue to use much TypeScript moving forward, because it seems to promote the classical inheritance style of thinking in a language that doesn’t need or want it.

    TL;DR: Prototypical/concatenative inheritance is much nicer than classical inheritance.

    That said, first-class support for TypeScript in Visual Studio Code is quite awesome. While implementing the data structures, I came up with a TypeScript/prototypical hybrid style for writing object factories. In this hybrid style, the only place I’m writing any TypeScript is using interfaces for prototypes. Let’s take a number class for example:

    interface NumberInterface {
      isEven()              : boolean
      multiplyByTwo()       : number
      divideBy(arg: number) : number
    }
    
    const number = (num: number) => {
      const prototype: NumberInterface = {
        isEven() {
          return this.number % 2 === 0
        },
        multiplyByTwo() {
          return this.number * 2
        },
        divideBy(arg) {
          if (arg === 0) {
            throw new Error('Cannot divide by 0')
          }
          return this.number / arg
        }
      }
    
      return Object.assign(Object.create(prototype), { number: num })
    }
    
    const two = number(2)
    console.log(two.isEven())        // true
    console.log(two.multiplyByTwo()) // 4
    console.log(two.divideBy(2))     // 1
    console.log(two.divideBy(0))     // Error: Cannot divide by 0
    

    I return a object whose prototype is prototype using Object.create, and its initial state using Object.assign.

    This style allows VSC to shout at me if the prototype doesn’t implement the interface correctly. It’s nice to have, but not worth switching over to a TypeScript workflow from the Babel workflow that I’m already used to.

  • Migrating to Visual Studio Code

    I’ve been testing out Visual Studio Code for writing Node stuff, and I really like what I’m seeing so far. I’d like to confess that 99.9% of the reason why I even considered trying it out in the first place was its ability to debug Node apps. I tried Intellij IDEA previously and was so put off by the IDE-like interface (my Eclipse days are still not quite past me) that I couldn’t bring myself to migrate over.

    On first boot I immediately taken aback by how familiar to Sublime Text the interface was. I might even add that it feels somewhat snappier, although I can’t pin it down to a specific thing.

    A comparison of VSC vs ST, listing only the features that I’ve used and enjoyed and the features I’m missing:

    What VSC has

    • Drag and dropping in the sidebar
    • Node debugging that actually works consistently and without fuss
      • If this was the only thing going for it I would still have used it
    • IntelliSense features
    • First class support for TypeScript
    • Nifty npm features

    What VSC doesn’t have

    • Tabs
      • Sublime Text has the same intuitive tab handling as Chrome, and I was very surprised to see VSC depart from this pervasive pattern, instead opting for a strange “Working Files” way of handling, well, working files. It’s not completely bad, just strange. I’d love to see the usual tab handling functionality introduced into VSC as an option in the future.
    • Find in Files
      • I use “Find in Files” very regularly, and Sublime Text’s way of presenting the search results is still more familiar for me. VSC’s search results is tucked into the criminally narrow sidebar, which makes it very difficult to inspect the results.
    • No Emmet/Zen Coding package
      • Not that applicable to Node development, but I still use it occasionally for writing JSX

    Babel/ES6 Support

    Of course, debugging my apps in VSC would mean that it has to be set up to run ES6 code, and I’m happy to report that this is very possible and very easy. In launch.json, simply set the runtimeExecutable to the babel-node binary in your project’s node_modules:

    {
      "program": "${workspaceRoot}/index.js",
      "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/babel-node"
    }
    

    Configure the rest of your launch.json as per VSC’s documentation.

    Note: There seems to be no good way of launching npm script commands from launch.json - will be investigating this in more detail.

    Key Bindings

    Most of the key bindings I use are the same. These are the only key bindings I’ve had to change so far to make it consistent with ST’s:

    [
      { "key": "cmd+r", "command": "workbench.action.showAllSymbols" },
      { "key": "cmd+t", "command": "workbench.action.quickOpen" },
      { "key": "cmd+l", "command": "expandLineSelection" }
    ]
    

    Theming

    I use Afterglow in ST, and I’m happy to report that there is also Afterglow for VSC (just search for “Afterglow” in Extensions).

    Packages

    I’ve also found the following packages to be useful so far:

    • ES6 Snippets
      • Not just ES6 - many handy JavaScript snippets waiting to expanded at the press of a ↹
    • Align
      • I use the Alignment package in ST a lot, and this one works just as well
    • Git History
      • For viewing Git history on a per-file basis or even per-line basis

    Git Support

    I prefer to manage my Git stuff in the command line or in Tower, so I don’t really care for VSC’s built-in Git support, although from cursory inspection it seems quite similar to SublimeGit (which I use only for git blame and git checkout).

  • Exposing React Performance Tools in the Browser Console

    The React docs on Performance Tools is quite lacking as to how it should be used, so I had to do some digging around to figure out how it worked.

    It turns out Perf.start() doesn’t work in component lifecycles1, raising an ugly internal error that hasn’t been properly dealt with yet (see this issue for more details).

    This prevents us from doing some things like:

    1. Calling Perf and measuring performance repeatedly.

    2. Using Perf to measure between arbitrary points in deeper parts of your component hierarchy.

    I solved these problems by exposing React’s performance tools in the browser. There are a few ways to do this. If you’re using webpack, you can use expose-loader, which allows us to attach modules to the global object:

    $ npm install expose-loader --save-dev
    
    module: {
      loaders: [
        { test: require.resolve("react-addons-perf"), loader: "expose?ReactPerf" }
      ]
    }
    

    You can then start measuring in the console at any time:

    // in browser console
    > ReactPerf.start()
    

    and you can call Perf.stop() in a component lifecycle method:

    import Perf from 'react-addons-perf'
    
    class SomeComponent extends React.Component {
    
      componentDidUpdate() {
        Perf.stop()
        Perf.printWasted()
      }
    
      render() { ... }
    }
    

    or in the browser console:

    // in browser console
    > ReactPerf.stop()
    > ReactPerf.printWasted()
    

    Footnotes

    1. perf.stop() and the rest of the printing methods do.

  • Circular References in GraphQL Type Definitions

    When defining GraphQL types, it’s common to run into situations when two types reference each other. This is a problem because one type will be undeclared or undefined when the other is evaluated.

    // Bad, `Item` is not defined (JavaScript actually means *undeclared* here)
    const User = new GraphQLObjectType({
      name: 'User',
      fields: {
        id   : { type: GraphQLString },
        email: { type: GraphQLString },
        items: {
          type: new GraphQLList(Item),
          resolve: () => { /* resolve function to get user's items */ }
        },
      }
    })
    
    const Item = new GraphQLObjectType({
      name: "Item",
      fields: {
        id:        { type: GraphQLString },
        name:      { type: GraphQLString },
        user: {
          type: User,
          resolve: () => { /* resolve function to get user of item */ }
        }
      }
    })
    
    // doesn't work either - `Item` is undefined, but `type` expects a GraphQL type
    let Item // declared, but has value of undefined
    const User = new GraphQLObjectType({
      name: 'User',
      fields: {
        id   : { type: GraphQLString },
        email: { type: GraphQLString },
        items: {
          type: new GraphQLList(Item),
          resolve: () => { /* resolve function to get user's items */ }
        },
      }
    })
    
    Item = ...
    

    To fix this, the reference JavaScript implementation allows us to indicate the fields using a function that returns an object, instead of a plain object. This function is lazily evaluated during runtime, so we will not run into problems with the interpreter.

    // Works!
    const User = new GraphQLObjectType({
      name: 'User',
      fields: () => ({
        id   : { type: GraphQLString },
        email: { type: GraphQLString },
        items: {
          type: new GraphQLList(Item),
          resolve: () => { /* resolve function to get user's items */ }
        },
      })
    })
    
    const Item = new GraphQLObjectType({
      name: "Item",
      fields: () => ({
        id:        { type: GraphQLString },
        name:      { type: GraphQLString },
        user: {
          type: User,
          resolve: () => { /* resolve function to get user of item */ }
        },
      })
    })
    
  • Exporting ES6 Library Modules as Global Scripts with Webpack

    After authoring a library (Remerge) using ES6 style modules, aside from consumption with npm, I also wanted to release it as a standalone script so that users could use it by simply including it with a simple script tag - well, if they wanted to, at least (appealing to the lowest common denominator here heh).

    The Scenario

    So I wanted to be able to do something like this:

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Remerge Example</title>
    </head>
    <body>
    
      <div id="main">
        // your beautiful site goes here
      </div>
    
      <script src="mainFunction.js"></script>
      <script src="utiltyFunctions.js"></script>
    
      <script>
        // use library here
        // `mainFunction` is a function exported as a global variable
        // `utiltyFunctions` is an object exported as a global variable, whose properties are utility functions
        var reducer = mainFunction(...)
        var someFunction = utiltyFunctions.someFunction(...)
      </script>
    
    </body>
    </html>
    

    Notice that both scripts have a slightly different export pattern. In my code, I wrote mainFunction such that it was a default export:

    const mainFunction = () => {
      // main function
    }
    
    export default mainFunction
    

    and utlityFunction as named exports, spread across a number of files (tackling the general case here):

    // utils.js
    export const someFunction1 = () => {
      // some function1
    }
    
    // more-utils.js
    export const someFunction2 = () => {
      // some function2
    }
    

    The Problem

    The problem is that, as it is, bundling these ES6 modules will result in objects that look like this:

    var mainFunction = {
      _es6module: true,
      default: // the actual mainFunction
    }
    

    which is technically usable, but to use it would look like:

    var something = mainFunction.default(...)
    

    which is a real PITA for ensuring a consistent API.

    The Fix

    The fix for this is simple: simply write a file that imports those ES6 modules the ES6 way, but exports them in nodeJS module.exports style. Webpack will then handle them correctly!

    For the top-level function export, simply export the function as is:

    // webpack/mainFunction.js
    import mainFunction from '../src/mainFunction'
    
    module.exports = mainFunction
    

    For the object whose properties should be utility functions, the solution is similarly straightforward - simply create an (in this case anonymous) object whose properties are those functions:

    // webpack/utilityFunctions.js
    import * as someFunctions1 from '../src/utils'
    import * as someFunctions2 from '../src/more-utils'
    
    module.exports = {
      ...someFunctions1,
      ...someFunctions2
    }
    

    For my library, I’ve placed these “helper” files in a webpack folder, as their sole purpose is for Webpack to generate the script files. You can place them anywhere it makes sense.

    The Webpack configuration for handling this is very simple (as far as build configs go):

    var webpack = require('webpack')
    
    module.exports = {
    
      entry: {
        mainFunction: './webpack/mainFunction.js',
        utilityFunctions: './webpack/utilityFunctions.js'
      },
    
      output: {
        path: __dirname + '/dist',
        filename: '[name].js',
        libraryTarget: 'var',
        // `library` determines the name of the global variable
        library: '[name]'
      },
    
      // don't run Babel on your library's dependencies
      module: {
        loaders: [
          { test: /\.js$/, exclude: /node_modules/, loader: 'babel' }
        ]
      },
    
      // uglify your scriptz
      plugins: [
        new webpack.optimize.UglifyJsPlugin({ minimize: true })
      ]
    
    }
    

    Then you can use them as shown in the HTML snippet above! For an actual live example of this in action, check out my library Remerge.