Giter VIP home page Giter VIP logo

typever's Introduction

TypVer

Build Status Version semantic-release

An opinionated versioning strategy for TypeScript ambient types

About The Problem

Picking version numbers for TypeScript ambient types is quite tricky. Versioning philosophies like SemVer don't quite get the job done when it comes to types. Let's look at a simple example

An Example

Let's say we have a vanilla JavaScript library called table-component whose version is currently 4.5.6. If they follow SemVer, we know some things about this version

In essence, for this code, consumers know whether it includes

  • ๐Ÿค• Big changes that may require modification of their app's code
  • ๐ŸŽ New features that shouldn't interfere with what already works
  • ๐Ÿ›  Small improvements and fixes that don't introduce any API changes of significance

However, let's say we have a library like @types/table-component that provides some type information to describe table-component's code. There's some more information we need to capture

๐Ÿ”ข +Info: Which version of table-component the types describe

This is a piece of information our consumers will certainly want to know, and there's no easy way to adhere to SemVer while also providing an answer to this question.

๐Ÿ’” +Info: Extra breaking changes

In addition to reflecting the breaking changes in table-component, @types/table-component may have its own breaking changes that are strictly related to the types themselves.

For example:

  • Dropping support for old TypeScript versions
  • Starting to require a generic parameter that was previously optional
  • Making types more specific

Think about the previous point about "which version does this describe?". Maybe now you can see why the SemVer, and "match the table-component version number" (sometimes referred to as "Lockstep") strategies both break down for types.

If we currently have a package.json like this

"table-component": "4.5.6",
"@types/table-component": "4.5.6"

You might guess that these types describe exactly the library version we're working with. However, what happens when drop support for TypeScript 2.4 (a breaking change). Semver would tell us to do this:

"table-component": "4.5.6",
"@types/table-component": "5.0.0" # SemVer?

and now it looks like our library and types don't match. If [email protected] is released we'd have to release a @types/[email protected]. How can our consumers tell the difference between a breaking change in the types, and type-alignment with breaking changes in the code our types describe?

If we try the "Lockstep" strategy, and match the library version number, we'd have to use something like pre-release versions

"table-component": "4.5.6",
"@types/table-component": "4.5.7-beta.1" # Lockstep?

but now we've deprived our users of the ability to protect themselves against breaking changes within the types

๐ŸŽ› -Info: Features

The job of ambient types is simply to describe some other piece of code, the concept of a "non-breaking feature" within the types themselves is extremely rare. If a change is made to improve the way the types describe their corresponding table-component code, that's a bug fix. All that's left to think about is whether it's breaking or non-breaking

๐Ÿ— -Info: Minor Releases

If the library our types describe follows SemVer, the types that work for [email protected] should be a superset of the types that describe [email protected]. Because of this, consumers should be able to use the latest @types/table-component@4.* with any table-component@4.* and not encounter any type errors. We're relying on this aspect of SemVer

Minor version Y (x.Y.z | x > 0) MUST be incremented if new, backwards compatible functionality is introduced to the public API.

which guarantees the backwards compatibility we need to mix newer types with older libraries (within the same major release)

A Solution

Before getting into a specific solution, let's lay out some goals

  • Make it clear to consumers, which major version of a library the types are designed to work with
  • Use npm and yarn commands the standard way to take in safe and non-breaking changes
  • Allow consumers to protect themselves from breaking changes
  • Compatibility with tools like dependabot and greenkeeper
  • Some flexibility within type versions to allow for breaking changes even between patch releases of the library they describe (i.e., if a breaking TypeScript change forces dropping old TS versions)

The Versioning Strategy

If we treat versions as X.Y.Z

  • X - Indicates the major release of a library that the types describe. As long as X follows the SemVer convention, this is all we need to track in order to maintain compatability.
  • Y - Indicates a breaking change in types, within the same X
  • Z - Indicates a non-breaking change in types, within the same Y
A concrete example: @types/ember and ember
// @types/ember v2.1.2

2  // Tracking the ember@2 release series
.
1  // Breaking change since @types/[email protected]
.
2  // Non-breaking change since @types/[email protected]

Using This Library

This library provides a CLI tool and a JavaScript API for managing versioned types that follow this style of versioning

Installation

Use your choice of package manager to add this package as a devDependency of your project

yarn add -D typever             # yarn
npm install --save-dev typever  # npm

Running the CLI command

Run this commmand, providing the package name, and optionally a types library name (defaults to "@types/<package-name>") to use.

typever check <package-name> [types-library-name]

You should get some feedback regarding the current state of your versions

Calling the script directly

import { readFileSync } from 'fs';
import { join } from 'path';
import { versionCheck } from 'typever';

const pkgPath = join(__dirName, '..', 'package.json');
const pkg = JSON.parse(
  readFileSync(pkgPath).toString();
);

const allDependencies = Object.assign({}, pkg.devDependencies, pkg.dependencies);

versionCheck(allDependencies, 'react', '@types/react').then(checkResult => {
  console.log(checkResult);
});

a sample of what checkResult looks lke:

{
  lib: { name: 'commander', target: '^2.17.1', version: '2.17.1' },
  types: {
    recommendedTarget: '~2.12.2',
    name: '@types/commander',
    target: '^2.12.2',
    version: '2.12.2'
  },
  result: {
    compatibility: 'warn',
    reason:
      'Type library target of "^2.12.2" will allow your app to take in breaking changes.\nThis is the SemVer equivalent of { "@types/commander": "*" }',
    suggestion:
      'Update package.json with dependency { "@types/commander": "~2.12.2" }'
  }
}

ยฉ 2018 Mike North

typever's People

Contributors

dependabot-support avatar ember-tomster avatar mike-north avatar renovate-bot avatar semantic-release-bot avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.