Issue 1:
Good progress is made on supporting the case of packages that carry their own typings in #2338.

That proposal doesn't currently deal with modules that do not carry their own typings, a.k.a. all modules that need typings from DefinitelyTyped.

This issue is to investigate possibilities of, and propose a (simple) solution for preventing problems when using (multiple versions of) external modules together.

TL;DR

No longer use declare module "..." { } in typings for external modules

Add an extra step to the resolution logic of #2338 to look up this type of external typings

Example scenario

myprogram

mylib

myutils@1.0

myotherlib

myutils@2.0

Suppose that both mylib and myotherlib export a function, that returns a value of a type defined in myutils.

Existing scenario

Likely, both mylib and myotherlib will each have a /// <reference path="./typings/tsd.d.ts" /> line, which again has a /// <reference path="./myutils/myutils.d.ts" /> line.

Problem

Both libs carry their own version of myutils.d.ts, which works fine as long as they are not used together.

However, when they are used together (as in this example), all the /// <reference ...> lines will (need to) be 'merged', which essentially means the declare module "myutils" { ... } from both mylib and myotherlib will end up in the same 'global module name namespace'.

This gives a compiler error, and even if the compiler would somehow allow it, would make it impossible to refer to either version of myutils.

Additionally, tools like dts-generator e.g. include the /// <reference> line inside of the declare blocks, which get ignored by the compiler. This leads to unknown-references when trying to use such a typing, and will typically be solved by adding e.g. a myutils/myutils.d.ts to myprogram/typings/tsd.d.ts, which will be wrong for one of the libs.

Solution

External modules have the nice property that there is no 'global namespace' (except the filesystem, maybe), and basically every reference is 'local'.

It makes sense to use the same referencing scheme that's used for resolving 'local' external modules (within a package) for 'normal' external modules (different npm packages).

Basically, the idea consists of:

No longer using declare module "..." { } in typings for external modules (to prevent the global namespace clash)

Adding an extra step to the resolution logic of #2338 to look up this type of external typings (e.g. in typings/ folder)

Advantages

Multiple versions of a package can co-exist in the same program/library

/// <reference> lines are no longer needed in most cases (except probably for e.g. importing Mocha's it() and other 'true' globals)

One format to rule them all: external module typings are already generated without declare module "..." { } by tsc, so all 'sorts' of external module typings will look the same

Gradual upgrade path: the tsd.d.ts-way will still work for packages that do still use declare module "..." { } (although it will still have the name-clash problem etc.)

Disadvantages

Typings on e.g. DefinitelyTyped will (gradually) need to be replaced with their non-wrapped version

Extra lookup step in the compiler

Location of these external typings (a.k.a. include path) needs to be configured somewhere and/or sensible default value chosen

Example 'new-style' typings

Most hand-crafted typings will typically look like:

/// myutils.d.ts
export interface BarType {
bar: number;
}
export declare function something(): BarType;

But just to make things more interesting, suppose the typings of myutils look like:

/// dist/bar.d.ts
export interface BarType {
bar: number;
}

/// dist/foo.d.ts
import bar = require("./bar");
export declare function something(): bar.BarType;

Nothing special here, this is what tsc generates today.

(Note: dist/ may be because someone used CoffeeScript, not TypeScript, right? :))

Now, the typings dir on e.g. DefinitelyTyped could look like:

DefinitelyTyped/myutils/latest/dist/bar.d.ts
DefinitelyTyped/myutils/latest/dist/foo.d.ts
DefinitelyTyped/myutils/1.0/dist/bar.d.ts
DefinitelyTyped/myutils/1.0/dist/foo.d.ts

(Or maybe 2.0 instead of latest, ideas welcome.)

And both mylib and myotherlib would have:

typings/myutils/dist/bar.d.ts
typings/myutils/dist/foo.d.ts

Looking up .d.ts

Given e.g. import { something } from "myutils" the compiler could use myutils/package.json's main property to get to ./dist/foo.js, which in turn would resolve to dist/foo.d.ts.

Nice and simple: no need to have support from the authors of myutils, no /// <reference> lines.

And it even supports the import bar = require("myutils/dist/bar") case.

Open questions

Use one typings dir for both 'wrapped' and 'unwrapped' typings?

First do a lookup for external modules already declare'ed, e.g. through tsd.d.ts? If so, would probably make first bullet usable, nice for gradual upgrade path of DT typings.

Most DT typings will not want to mimic exact filesystem structure of package, using e.g. myutils/latest/index.d.ts will probably work out-of-the-box with external module resolution logic, but myutils/latest/myutils.d.ts or even myutils/myutils.d.ts may be easier for filename in editor tab?

Good idea? Bad idea?

Issue 2:
TypeScript Version:

1.7.5 / 1.8.0-beta / nightly (1.9.0-dev.20160217)

Code

// A self-contained demonstration of the problem follows...
this._register('vscode.diff', (left: URI, right: URI, label: string) => {
return this._commands.executeCommand('_workbench.diff', left, right, label);
}, {
description: 'Opens the provided resources in the diff editor to compare their contents.',
args: [
{ name: 'left', description: 'Uri of the resource for the left hand side of the diff editor', constraint: value => value instanceof URI },
{ name: 'right', description: 'Uri of the resource for the right hand side of the diff editor', constraint: value => value instanceof URI },
{ name: 'label', description: 'Label to use for the diff editor', constraint: value => typeof value === 'string' }
]
});

Expected behavior:

goto ts playground

paste the code and invoke format

you get this (note the wrong indent on the last 7 lines):

this._register('vscode.diff', (left: URI, right: URI, label: string) => {
return this._commands.executeCommand('_workbench.diff', left, right, label);
}, {
description: 'Opens the provided resources in the diff editor to compare their contents.',
args: [
{ name: 'left', description: 'Uri of the resource for the left hand side of the diff editor', constraint: value => value instanceof URI },
{ name: 'right', description: 'Uri of the resource for the right hand side of the diff editor', constraint: value => value instanceof URI },
{ name: 'label', description: 'Label to use for the diff editor', constraint: value => typeof value === 'string' }
]
});

Actual behavior:

indent properly