Skip to content

Reconsider TypeScript #126

@jednano

Description

@jednano

TypeScript type definitions were already requested in #20 and #66 back in 2016-2017, but the landscape has changed much since then.

Two concerns were expressed in #20, that you would like to avoid, which I will address below, but first let me state the value proposition.

Value Proposition

For a library such as this, it makes all the sense in the world for the source to be written in TypeScript for the following reasons:

  1. The type definition files (*.d.ts) can be generated at compile time for free. Nobody has to manually update these files, leading to version out-of-sync issues.
  2. Types remain in sync with each version that is published. You just can't get this feature without TS source code.
  3. You don't have to install two packages for each "just" package (e.g., npm install --save just-omit && npm install --save-dev @types/just-omit).
  4. Users who don't use TypeScript can still benefit via Automatic Type Acquisition.

Transpilation step

There's obviously no getting around this one if TS were to be used, but I'd like to know, specifically, what the concerns around the transpilation step are.

Size increase

This one is probably a misconception, an outdated fear or an exaggeration. As a superset of JavaScript, TypeScript seeks not to add any language constructs of their own. As long as we steer away from inheritance and down-level compilation, there's really nothing to fear here. All the type information and interfaces disappear at compile time.

Let's take just-omit as an example. Currently, if I remove the comments, the file size is 193 bytes min / 177 bytes min + gzip.

If I were to convert it into TypeScript, it would look something like this:

export = omit

/**
 * The opposite of `just-pick`; this method creates an object composed of the
 * own and inherited enumerable properties of `object` that are not omitted.
 * 
 * @category Object
 * @returns A new object with specified keys omitted from the source `object`.
 * @example ...
 */
function omit<T extends object, K extends keyof T>(
  /**
   * The source object.
   */
  object: T | null | undefined,
  /**
   * The property names to omit.
   */
  ...paths: Array<K | ReadonlyArray<K>>
) {
  const result = {} as Pick<T, Exclude<keyof T, K>>;
  for (const prop in object) {
    if (!object.hasOwnProperty || object.hasOwnProperty(prop)) {
      if (paths.indexOf(prop as unknown as K) === -1) {
        result[prop as string] = object[prop];
      }
    }
  }
  return result
}

Which compiles to 214 bytes min / 190 bytes min + gzip:

"use strict";
function omit(object) {
    var paths = [];
    for (var _i = 1; _i < arguments.length; _i++) {
        paths[_i - 1] = arguments[_i];
    }
    var result = {};
    for (var prop in object) {
        if (!object.hasOwnProperty || object.hasOwnProperty(prop)) {
            if (paths.indexOf(prop) === -1) {
                result[prop] = object[prop];
            }
        }
    }
    return result;
}
module.exports = omit;

The delta is only 21 bytes and 13 bytes, respectively, and I could have avoided that if I stuck to the current just-omit implementation and didn't use the spread (...) operator for paths.

Point is, it's basically the same, but you gain so much value in serving the community with the type information they need. Even if they aren't using TypeScript, editors like vscode can still pull-in type information via type acquisition, so everybody wins.

Automatic Type Acquisition works for dependencies downloaded by npm (specified in package.json), Bower (specified in bower.json), and for many of the most common libraries listed in your folder structure (for example jquery-3.1.1.min.js).

Conclusion

As long as you're open to the idea, I think the community can start to submit PRs incrementally. There's no reason everything has to be done all at once.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions