Issue 1:
TypeScript Version:

1.8.10

Code

import * as ts from "typescript";

// Note: this uses ts.formatting which is part of the typescript 1.4 package but is not currently
// exposed in the public typescript.d.ts. The typings should be exposed in the next release.
function format(text: string) {
let options = getDefaultOptions();

// Parse the source text
let sourceFile = ts.createSourceFile("file.ts", text, ts.ScriptTarget.Latest, /*setParentPointers*/ true);

// Get the formatting edits on the input sources
let edits = (<any>ts).formatting.formatDocument(sourceFile, getRuleProvider(options), options);

// Apply the edits on the input code
return applyEdits(text, edits);

function getRuleProvider(options: ts.FormatCodeOptions) {
// Share this between multiple formatters using the same options.
// This represents the bulk of the space the formatter uses.
let ruleProvider = new (<any>ts).formatting.RulesProvider();
ruleProvider.ensureUpToDate(options);
return ruleProvider;
}

function applyEdits(text: string, edits: ts.TextChange[]): string {
// Apply edits in reverse on the existing text
let result = text;
for (let i = edits.length - 1; i >= 0; i--) {
let change = edits[i];
let head = result.slice(0, change.span.start);
let tail = result.slice(change.span.start + change.span.length)
result = head + change.newText + tail;
}
return result;
}

function getDefaultOptions(): ts.FormatCodeOptions {
return {
IndentSize: 4,
IndentStyle: 1,
TabSize: 4,
NewLineCharacter: '\n',
ConvertTabsToSpaces: false,
InsertSpaceAfterCommaDelimiter: true,
InsertSpaceAfterSemicolonInForStatements: true,
InsertSpaceBeforeAndAfterBinaryOperators: true,
InsertSpaceAfterKeywordsInControlFlowStatements: true,
InsertSpaceAfterFunctionKeywordForAnonymousFunctions: false,
InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: false,
InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: false,
InsertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: false,
PlaceOpenBraceOnNewLineForFunctions: false,
PlaceOpenBraceOnNewLineForControlBlocks: false,
};
}
}

let code = "var a=function(v:number){\n return 0+1+2+3;\n}";
let result = format(code);
console.log(result);

Expected behavior:

The return line should be indented with tab.

Actual behavior:

It's actually left untouched because at input it is already indented with 4 spaces and IndentSize is set to 4. This is, however, counter-intuitive, the formatter should fix the indentation to tabs, in my opinion.

The reason this happens is in https://github.com/Microsoft/TypeScript/blob/d960200dac73d077a66b8ac6ef0648895dc3493e/src/services/formatting/formatting.ts#L869

where the token start position (4) is compared to expected indent size, but there is no check whether the indentation is made from spaces.

Issue 2:
We have a typescript application and a use a file per class. There are lots of benefits to this the major one being source control conflict reduction.

We compile our app using the --out compiler flag but I think there is room for some serious optimization of the compilers output for modules.

Currently if you have two classes defined in separate files the compile generates the following JavaScript.

var Example;
(function (Example) {
(function (Nested) {
(function (Issue) {
var bar = (function () {
function bar() {
}
return bar;
})();
Issue.bar = bar;
})(Nested.Issue || (Nested.Issue = {}));
var Issue = Nested.Issue;
})(Example.Nested || (Example.Nested = {}));
var Nested = Example.Nested;
})(Example || (Example = {}));

var Example;
(function (Example) {
(function (Nested) {
(function (Issue) {
var foo = (function () {
function foo() {
}
return foo;
})();
Issue.foo = foo;
})(Nested.Issue || (Nested.Issue = {}));
var Issue = Nested.Issue;
})(Example.Nested || (Example.Nested = {}));
var Nested = Example.Nested;
})(Example || (Example = {}));

I suggest a compiler flag that composes all classes/ functions etc under a single module declaration? So the output code would be like the example below. This would dramatically reduce the size of the JavaScript the compiler outputs. I estimate that our app which currently compiles to around 15,000 lines of probably be only be 2000 lines if this were available.

var Example;
(function (Example) {
(function (Nested) {
(function (Issue) {
var bar = (function () {
function bar() {
}
return bar;
})();
Issue.bar = bar;
var foo = (function () {
function foo() {
}
return foo;
})();
Issue.foo = foo;
})(Nested.Issue || (Nested.Issue = {}));
var Issue = Nested.Issue;
})(Example.Nested || (Example.Nested = {}));
var Nested = Example.Nested;
})(Example || (Example = {}));