npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@microsoft/msfs-ts-transformer

v1.0.0

Published

MSFS Typescript Transformer

Readme

MSFS Typescript Transformer

A transformer that optimizes the Javascript code emitted by the Typescript compiler for use in Microsoft Flight Simulator's CoherentGT environment.

Usage

  1. Install ts-patch.
  2. Install the transformer package: npm i @microsoft/msfs-ts-transformer --save-dev
  3. Add the transformer package as a compiler plugin in your project's tsconfig.json:
{
  "compilerOptions": {
    "plugins": [
      { "transform": "@microsoft/msfs-ts-transformer" },
    ],
  },
}
  1. Run ts-patch to inject the transformer as a compiler plugin into Typescript. Refer to the ts-patch documentation on how to run ts-patch.

Optimizations applied

This transformer applies the following optimizations to Javascript code emitted by the Typescript compiler. Note that the transformer has no effect on the type-checking phase, nor does it alter emitted declaration (.d.ts) files.

For-of statements

The transformer converts for-of statements that iterate through array-like objects into classical for loops. For example:

// Typescript:
const array = [0, 1];
for (const element of array) {
  // Do stuff.
}

// Emitted JS without transformer:
const array = [0, 1];
for (const element of array) {
  // Do stuff.
}

// Emitted JS with transformer:
const array = [0, 1];
for (let _i_1 = 0; _i_1 < array.length; ++_i_1) {
  const element = array[_i_1];
  // Do stuff.
}

// In cases where the expression of the for-of statement is not an identifier, the value of the expression will be
// memoized into a new const to ensure that the expression is evaluated exactly the same number of times as it would be
// in the un-optimized code:

// Typescript:
for (const element of [0, 1]) {
  // Do stuff.
}

// Emitted JS without transformer:
for (const element of [0, 1]) {
  // Do stuff.
}

// Emitted JS with transformer:
const _arr_1 = [0, 1];
for (let _i_1 = 0; _i_1 < _arr_1.length; ++_i_1) {
  const element = _arr_1[_i_1];
  // Do stuff.
}

For-of statements iterate through objects using the iterator returned by [Symbol.iterator](). This type of iteration is not well-optimized by CoherentGT's Javascript interpreter or compiler and incurs non-trivial execution time and memory allocation overhead compared to iteration using a classical for loop. As a result, it is always faster to iterate through arrays using classical for loops than for-of statements.

This optimization works for all object types that are considered "array-like", not just the built-in Array type. An "array-like" object is any object that satisfies the following interface:

interface ArrayLike<T> extends Iterable<T> {
  readonly [index: number]: T;
  readonly length: number;
}

This means that the optimization will work for, among other things, the built-in typed arrays (e.g. Float64Array).

In cases where Typescript was unable to resolve the type of the object being iterated by the for-of statement, the optimization will not be applied. This includes cases where the type of the iterated object is the any type:

// Will *not* be optimized.
for (const element of [] as any) {
}

Array destructuring

The transformer de-sugars array-destructuring syntax when the object being destructured can be directly indexed instead. For example:

// Typescript:
const array = [0, 1];
const [a, b] = array;

// Emitted JS without transformer:
const array = [0, 1];
const [a, b] = array;

// Emitted JS with transformer:
const array = [0, 1];
const a = array[0], b = array[1];

// Omitted expressions inside the destructuring syntax are supported:

// Typescript:
const array = [0, 1];
const [, b] = array;

// Emitted JS without transformer:
const array = [0, 1];
const [, b] = array;

// Emitted JS with transformer:
const array = [0, 1];
const b = array[1];

// In cases where the right-hand-side (RHS) of the destructuring expression is not an identifier, the value of the
// RHS will be memoized into a new const to ensure that the RHS is evaluated exactly the same number of times as it
// would be in the un-optimized code:

// Typescript:
const [a, b] = [0, 1];

// Emitted JS without transformer:
const [a, b] = [0, 1];

// Emitted JS with transformer:
const _arr_1 = [0, 1];
const a = _arr_1[0], b = _arr_1[1];

Behind the scenes, array destructuring relies on iterating through the destructured object using the iterator returned by [Symbol.iterator](). Iterating through objects this way incurs non-trivial execution time and memory allocation overhead. As a result, it is always faster to destructure objects "manually" by directly indexing the object.

This optimization works for all object types that can be indexed by number, not just the built-in Array type. In other words, all objects that satisfy the following interface:

interface Indexable<T> extends Iterable<T> {
  readonly [index: number]: T;
}

This means that the optimization will work for, among other things, the built-in typed arrays (e.g. Float64Array).

In cases where Typescript was unable to resolve the type of the object being destructured, the optimization will not be applied. This includes cases where the type of the destructured object is the any type:

// Will *not* be optimized.
const [a, b] = [0, 1] as any;

Optimization will also not be applied when destructuring uses the rest (...) operator or when any variable on the left-hand side of the destructuring pattern has an initializer:

// Will *not* be optimized.
const array = [0, 1];
const [a, ...b] = array;
// Will *not* be optimized.
const array = [0, 1];
const [a = 5, b] = array;

In addition to variable declarations, the following patterns are also optimized when using array-destructuring syntax:

Variable assignment:

// Typescript:
const array = [0, 1];
let a: number, b: number;
[a, b] = array;

// Emitted JS without transformer:
const array = [0, 1];
let a, b;
[a, b] = array;

// Emitted JS with transformer:
const array = [0, 1];
let a, b;
a = array[0], b = array[1], array;

// Note that the optimized code always ends with a reference to the destructured object.
// This is so that code that references the result of the original assignment expression still works properly:

// Typescript:
const array = [0, 1];
let a: number, b: number;
const sorted = ([a, b] = array).sort();

// Emitted JS without transformer:
const array = [0, 1];
let a, b;
const sorted = ([a, b] = array).sort();

// Emitted JS with transformer:
const array = [0, 1];
let a, b;
const sorted = (a = array[0], b = array[1], array).sort();

Parameter declaration:

// Typescript:
function foo([a, b]: number[]): void {
  // Do stuff.
}

// Emitted JS without transformer:
function foo([a, b]) {
  // Do stuff.
}

// Emitted JS with transformer:
function foo(_arrArg_1) {
  let a = _arrArg_1[0], b = _arrArg_1[1];
  // Do stuff.
}

// NOTE: If a parameter references one of the variables bound by the destructuring syntax in its initializer,
// then the destructured parameter will not be optimized:

// Will *not* be optimized.
function foo([a, b]: number[], c = a): void {
  // Do stuff.
}

For-of statement initializer:

// Typescript:
for (const [key, value] of new Map()) {
  // Do stuff.
}

// Emitted JS without transformer:
for (const [key, value] of new Map()) {
  // Do stuff.
}

// Emitted JS with transformer:
for (const _arr_1 of new Map()) {
  const key = _arr_1[0], value = _arr_1[1];
  // Do stuff.
}