![Page 1: patterns TypeScript size interface IModelChangeAccessor { insertText(position:IPosition, text:string): IEditorPosition; deleteText(range:IRange):](https://reader030.vdocuments.mx/reader030/viewer/2022013004/56649d135503460f949e6a4a/html5/thumbnails/1.jpg)
![Page 2: patterns TypeScript size interface IModelChangeAccessor { insertText(position:IPosition, text:string): IEditorPosition; deleteText(range:IRange):](https://reader030.vdocuments.mx/reader030/viewer/2022013004/56649d135503460f949e6a4a/html5/thumbnails/2.jpg)
Erich GammaDistinguished EngineerVSPlatform Tools/Monaco
Surviving Application Scale JavaScript - TypeScript in the Trenches
3-583
![Page 3: patterns TypeScript size interface IModelChangeAccessor { insertText(position:IPosition, text:string): IEditorPosition; deleteText(range:IRange):](https://reader030.vdocuments.mx/reader030/viewer/2022013004/56649d135503460f949e6a4a/html5/thumbnails/3.jpg)
Web based development tools, platform, and cloud services
What do we do?
![Page 4: patterns TypeScript size interface IModelChangeAccessor { insertText(position:IPosition, text:string): IEditorPosition; deleteText(range:IRange):](https://reader030.vdocuments.mx/reader030/viewer/2022013004/56649d135503460f949e6a4a/html5/thumbnails/4.jpg)
Team Foundation Server
![Page 5: patterns TypeScript size interface IModelChangeAccessor { insertText(position:IPosition, text:string): IEditorPosition; deleteText(range:IRange):](https://reader030.vdocuments.mx/reader030/viewer/2022013004/56649d135503460f949e6a4a/html5/thumbnails/5.jpg)
IE F12 Source Code Viewer
![Page 6: patterns TypeScript size interface IModelChangeAccessor { insertText(position:IPosition, text:string): IEditorPosition; deleteText(range:IRange):](https://reader030.vdocuments.mx/reader030/viewer/2022013004/56649d135503460f949e6a4a/html5/thumbnails/6.jpg)
TypeScript Playground
![Page 7: patterns TypeScript size interface IModelChangeAccessor { insertText(position:IPosition, text:string): IEditorPosition; deleteText(range:IRange):](https://reader030.vdocuments.mx/reader030/viewer/2022013004/56649d135503460f949e6a4a/html5/thumbnails/7.jpg)
WinJS Playground
![Page 8: patterns TypeScript size interface IModelChangeAccessor { insertText(position:IPosition, text:string): IEditorPosition; deleteText(range:IRange):](https://reader030.vdocuments.mx/reader030/viewer/2022013004/56649d135503460f949e6a4a/html5/thumbnails/8.jpg)
OneDrive
![Page 9: patterns TypeScript size interface IModelChangeAccessor { insertText(position:IPosition, text:string): IEditorPosition; deleteText(range:IRange):](https://reader030.vdocuments.mx/reader030/viewer/2022013004/56649d135503460f949e6a4a/html5/thumbnails/9.jpg)
Visual Studio Online Monaco
![Page 10: patterns TypeScript size interface IModelChangeAccessor { insertText(position:IPosition, text:string): IEditorPosition; deleteText(range:IRange):](https://reader030.vdocuments.mx/reader030/viewer/2022013004/56649d135503460f949e6a4a/html5/thumbnails/10.jpg)
The Road to Monaco
Small 50 kLOC
ModulesClasses
Promises
10% Typescript
Medium100 kLOC
“AMD”Lazy Loaded Contributions
50% Typescript
Larger200 kLOC
ComponentsAPI
Dependency Injection
100% Typescript
patterns
TypeScript
2011
2013
2012
size
![Page 11: patterns TypeScript size interface IModelChangeAccessor { insertText(position:IPosition, text:string): IEditorPosition; deleteText(range:IRange):](https://reader030.vdocuments.mx/reader030/viewer/2022013004/56649d135503460f949e6a4a/html5/thumbnails/11.jpg)
We enjoy programming in JavaScript, but…
![Page 12: patterns TypeScript size interface IModelChangeAccessor { insertText(position:IPosition, text:string): IEditorPosition; deleteText(range:IRange):](https://reader030.vdocuments.mx/reader030/viewer/2022013004/56649d135503460f949e6a4a/html5/thumbnails/12.jpg)
Organizing a large and growing code base Need to come up with “compensating” patterns for classes and
modules/namespaces
Refactoring JavaScript code is difficult “JavaScript code ‘rots’ over time” “Writing JavaScript code in a large project is like carving code in stone”
Describing APIs Keep the description in synch with the implementation
Concerns with JavaScript
![Page 13: patterns TypeScript size interface IModelChangeAccessor { insertText(position:IPosition, text:string): IEditorPosition; deleteText(range:IRange):](https://reader030.vdocuments.mx/reader030/viewer/2022013004/56649d135503460f949e6a4a/html5/thumbnails/13.jpg)
Optional and structural typing Fewer type annotations are necessary than you think
Classes, modules Formalization of common JavaScript patterns
Interfaces Interfaces named object types for describing the shape of JavaScript
objects
TypeScript to the Rescue…
![Page 14: patterns TypeScript size interface IModelChangeAccessor { insertText(position:IPosition, text:string): IEditorPosition; deleteText(range:IRange):](https://reader030.vdocuments.mx/reader030/viewer/2022013004/56649d135503460f949e6a4a/html5/thumbnails/14.jpg)
TypeScript at Work: Interfaces
interface IModelChangeAccessor {insertText(position:IPosition, text:string): IEditorPosition;deleteText(range:IRange): IDeleteTextResult;
}
interface IEditableTextModel {change(callback:
(changeAccessor:IModelChangeAccessor)=>any): …}
Interfaces to be implemented
![Page 15: patterns TypeScript size interface IModelChangeAccessor { insertText(position:IPosition, text:string): IEditorPosition; deleteText(range:IRange):](https://reader030.vdocuments.mx/reader030/viewer/2022013004/56649d135503460f949e6a4a/html5/thumbnails/15.jpg)
TypeScript at Work: Interfaces
export interface IValidationFilter {(resource:IEventEmitter): boolean;
}
public constructor(filter:IValidationFilter) {}
new Validator((resource)=>this.includeModel(resource));
Callbacks
![Page 16: patterns TypeScript size interface IModelChangeAccessor { insertText(position:IPosition, text:string): IEditorPosition; deleteText(range:IRange):](https://reader030.vdocuments.mx/reader030/viewer/2022013004/56649d135503460f949e6a4a/html5/thumbnails/16.jpg)
TypeScript at Work: Interfaces
interface ICommonEditorOptions {selectOnLineNumbers?:boolean;glyphMargin?:boolean;roundedSelection?:boolean;theme?:string;readOnly?:boolean;//…
}
Option bags
![Page 17: patterns TypeScript size interface IModelChangeAccessor { insertText(position:IPosition, text:string): IEditorPosition; deleteText(range:IRange):](https://reader030.vdocuments.mx/reader030/viewer/2022013004/56649d135503460f949e6a4a/html5/thumbnails/17.jpg)
TypeScript at Work: Interfaces
var options:IBuildData = JSON.parse(req.responseText);
export interface IBuildData {requestId:string;logOutput?:string;buildOutput?:BuildOutput;killOutput?:KillOutput;
}
JSON structures
![Page 18: patterns TypeScript size interface IModelChangeAccessor { insertText(position:IPosition, text:string): IEditorPosition; deleteText(range:IRange):](https://reader030.vdocuments.mx/reader030/viewer/2022013004/56649d135503460f949e6a4a/html5/thumbnails/18.jpg)
TypeScript at Work: Interfaces
declare module WinJS { module Binding {
//... } } class Promise<T> { //... }}
External types from other libraries
![Page 19: patterns TypeScript size interface IModelChangeAccessor { insertText(position:IPosition, text:string): IEditorPosition; deleteText(range:IRange):](https://reader030.vdocuments.mx/reader030/viewer/2022013004/56649d135503460f949e6a4a/html5/thumbnails/19.jpg)
Promises Pattern
promise.then(onFulfilled, onRejected);An object representing a value which may not yet have been computed onFulFilled
called after a promise is fulfilled, with the promise’s value as its first argument
onRejected called after a promise is rejected, with the promise’s reason as its first argument
http://promises-aplus.github.io/promises-spec/https://github.com/promises-aplus/promises-spec/blob/master/implementations.md
promise.then((result) => {...}, (err) => {...});
![Page 20: patterns TypeScript size interface IModelChangeAccessor { insertText(position:IPosition, text:string): IEditorPosition; deleteText(range:IRange):](https://reader030.vdocuments.mx/reader030/viewer/2022013004/56649d135503460f949e6a4a/html5/thumbnails/20.jpg)
class Promise<T> { then<U>(success?: (value: T) => Promise<U>, error?: (error: any) => Promise<U>, progress?: (progress: any) => void): Promise<U>; //…}
export interface ITypeDeclarationSupport { findTypeDeclaration(position:Editor.IPosition):Promise<IReference>;}
TypeScript at Work: Generics
![Page 21: patterns TypeScript size interface IModelChangeAccessor { insertText(position:IPosition, text:string): IEditorPosition; deleteText(range:IRange):](https://reader030.vdocuments.mx/reader030/viewer/2022013004/56649d135503460f949e6a4a/html5/thumbnails/21.jpg)
https://github.com/borisyankov/DefinitelyTyped
TypeScript Type Definitions
TSD: a package manager to search and install TypeScript definition files directly from the DefinitelyTyped repository.
![Page 22: patterns TypeScript size interface IModelChangeAccessor { insertText(position:IPosition, text:string): IEditorPosition; deleteText(range:IRange):](https://reader030.vdocuments.mx/reader030/viewer/2022013004/56649d135503460f949e6a4a/html5/thumbnails/22.jpg)
TypeScript at Work: Modules
We started with internal modules
![Page 23: patterns TypeScript size interface IModelChangeAccessor { insertText(position:IPosition, text:string): IEditorPosition; deleteText(range:IRange):](https://reader030.vdocuments.mx/reader030/viewer/2022013004/56649d135503460f949e6a4a/html5/thumbnails/23.jpg)
The Road to Monaco
Small 50 kLOC
ModulesClasses
InterfacesPromises
10% Typescript
Medium100 kLOC
“AMD”Lazy Loaded Contributions
50% Typescript
Larger200 kLOC
ComponentsAPI
Dependency Injection
100% Typescript
patterns
TypeScript
2011
2013
2012
size
![Page 24: patterns TypeScript size interface IModelChangeAccessor { insertText(position:IPosition, text:string): IEditorPosition; deleteText(range:IRange):](https://reader030.vdocuments.mx/reader030/viewer/2022013004/56649d135503460f949e6a4a/html5/thumbnails/24.jpg)
Modules are open undisciplined name space contributions…
You can have cyclic dependencies without noticing…
Name spaces have no relationship to the code organization on disk Renaming files/name spaces is no fun…
Code organization started to rot
Code Organization Pains
![Page 25: patterns TypeScript size interface IModelChangeAccessor { insertText(position:IPosition, text:string): IEditorPosition; deleteText(range:IRange):](https://reader030.vdocuments.mx/reader030/viewer/2022013004/56649d135503460f949e6a4a/html5/thumbnails/25.jpg)
Growing Pains: Order Matters…
![Page 26: patterns TypeScript size interface IModelChangeAccessor { insertText(position:IPosition, text:string): IEditorPosition; deleteText(range:IRange):](https://reader030.vdocuments.mx/reader030/viewer/2022013004/56649d135503460f949e6a4a/html5/thumbnails/26.jpg)
Growing Pains: Dependencies…
“… our dependency graph was such a mess that each area had a dependency on just about every other area.”
![Page 27: patterns TypeScript size interface IModelChangeAccessor { insertText(position:IPosition, text:string): IEditorPosition; deleteText(range:IRange):](https://reader030.vdocuments.mx/reader030/viewer/2022013004/56649d135503460f949e6a4a/html5/thumbnails/27.jpg)
Growing Pains: Eager loading
![Page 28: patterns TypeScript size interface IModelChangeAccessor { insertText(position:IPosition, text:string): IEditorPosition; deleteText(range:IRange):](https://reader030.vdocuments.mx/reader030/viewer/2022013004/56649d135503460f949e6a4a/html5/thumbnails/28.jpg)
Separately loaded code referenced using external module names
Implemented in separate source files Entities are private unless exported
TypeScript: External Modules
File main.ts:import adder= require("./adder"); adder.add(3,4);
File adder.ts: export function add(op1: number, op2: number):number {
return op1+op2;}
![Page 29: patterns TypeScript size interface IModelChangeAccessor { insertText(position:IPosition, text:string): IEditorPosition; deleteText(range:IRange):](https://reader030.vdocuments.mx/reader030/viewer/2022013004/56649d135503460f949e6a4a/html5/thumbnails/29.jpg)
CommonJS used by node.js
Asynchronous Module Definition (AMD) requires an AMD compliant module loader, e.g. requireJS
TypeScript: Module Patterns
define(‘main’, [‘adder'], function(adder) { // code goes here adder.add()});
var adder = require(“adder”);adder.add()
tsc --module amd main.ts
tsc --module commonjs main.ts
![Page 30: patterns TypeScript size interface IModelChangeAccessor { insertText(position:IPosition, text:string): IEditorPosition; deleteText(range:IRange):](https://reader030.vdocuments.mx/reader030/viewer/2022013004/56649d135503460f949e6a4a/html5/thumbnails/30.jpg)
AMD in TypeScript vs. JavaScript
AMD in JavaScript
define([‘…./winjs.base‘, ‘…./zoneWidget’], function(WinJS, ZoneWidget) { … });
AMD in TypeScriptimport WinJS= require('vs/base/lib/winjs');import ZoneWidget = require('vs/editor/zoneWidget');
![Page 31: patterns TypeScript size interface IModelChangeAccessor { insertText(position:IPosition, text:string): IEditorPosition; deleteText(range:IRange):](https://reader030.vdocuments.mx/reader030/viewer/2022013004/56649d135503460f949e6a4a/html5/thumbnails/31.jpg)
Server uses node.js Migrated server to TypeScript once a node.d.ts file became available
Client migrated to AMD and converted to TypeScript
Common module syntax enables code sharing between client and server
Monaco
![Page 32: patterns TypeScript size interface IModelChangeAccessor { insertText(position:IPosition, text:string): IEditorPosition; deleteText(range:IRange):](https://reader030.vdocuments.mx/reader030/viewer/2022013004/56649d135503460f949e6a4a/html5/thumbnails/32.jpg)
“It feels like fresh showered. Self contained modules, no more cycles, no more globals, clean file system structure”
After the AMD Migration Impressions
![Page 33: patterns TypeScript size interface IModelChangeAccessor { insertText(position:IPosition, text:string): IEditorPosition; deleteText(range:IRange):](https://reader030.vdocuments.mx/reader030/viewer/2022013004/56649d135503460f949e6a4a/html5/thumbnails/33.jpg)
AMD Applied – Lazy Loadingcsharp.ts
export class CSMode extends AbstractMode { constructor() { super('vs.languages.csharp'); } // lots of code …. }
csharp.contribution.ts
modeRegistry.registerMode( [‘text/x-csharp'], new Platform.Descriptor( 'vs/languages/csharp/csharp', ‘CSMode'));
Registered on start-up Loaded on demand
![Page 34: patterns TypeScript size interface IModelChangeAccessor { insertText(position:IPosition, text:string): IEditorPosition; deleteText(range:IRange):](https://reader030.vdocuments.mx/reader030/viewer/2022013004/56649d135503460f949e6a4a/html5/thumbnails/34.jpg)
Pain: “global” CSS files Want to package CSS files with the JS files into modules Want to express CSS file dependencies in code
AMD loader plugins Required module path can refer to a plugin “plugin!/” We implemented a css loader plugin, that allows to define:
define(["require", "vs/css!./actionbar", ...], …) CSS dependencies expressed in a pragma
AMD Applied – CSS Dependencies
![Page 35: patterns TypeScript size interface IModelChangeAccessor { insertText(position:IPosition, text:string): IEditorPosition; deleteText(range:IRange):](https://reader030.vdocuments.mx/reader030/viewer/2022013004/56649d135503460f949e6a4a/html5/thumbnails/35.jpg)
The Road to Monaco
Small 50 kLOC
ModulesClasses
InterfacesPromises
10% Typescript
Medium100 kLOC
“AMD”Lazy Loaded Contributions
50% Typescript
Larger200 kLOC
ComponentsAPI
Dependency Injection
100% Typescript
patterns
TypeScript
2011
2013
2012
size
![Page 36: patterns TypeScript size interface IModelChangeAccessor { insertText(position:IPosition, text:string): IEditorPosition; deleteText(range:IRange):](https://reader030.vdocuments.mx/reader030/viewer/2022013004/56649d135503460f949e6a4a/html5/thumbnails/36.jpg)
Migration is code clean-up but real work… Velocity around 300 LOCs per hour No implicit ‘anys’ No missing return types
Towards 100% TypeScript
“As I did conversions, I began typing various object literals I was passing around as interfaces. Soon enough, I realized how inconsistent I was, the same data was flowing around in at least 3 different formats. This is because of the easiness through which you can create literals in JavaScript …. Need some placeholder for data?... Just create a new literal object.”
![Page 37: patterns TypeScript size interface IModelChangeAccessor { insertText(position:IPosition, text:string): IEditorPosition; deleteText(range:IRange):](https://reader030.vdocuments.mx/reader030/viewer/2022013004/56649d135503460f949e6a4a/html5/thumbnails/37.jpg)
Reuse TypeScript code as ‘binary’ JS components with a declarations file
Example using TypeScript language services as a component Compiler and language services > 30kLOC of TypeScript
Generates a typescriptservices.d.ts
Componentization
tsc –declarations –out typescriptservices.js typescript.ts
![Page 38: patterns TypeScript size interface IModelChangeAccessor { insertText(position:IPosition, text:string): IEditorPosition; deleteText(range:IRange):](https://reader030.vdocuments.mx/reader030/viewer/2022013004/56649d135503460f949e6a4a/html5/thumbnails/38.jpg)
We were on the bleeding edge… …but we expected it and had plenty of band aid
We would do it again, the benefits outweigh the pains Confidence, refactoring agility, tooling, fun
We would start with TypeScript (and CommonJS/AMD) from the beginning
TS Retrospective
![Page 39: patterns TypeScript size interface IModelChangeAccessor { insertText(position:IPosition, text:string): IEditorPosition; deleteText(range:IRange):](https://reader030.vdocuments.mx/reader030/viewer/2022013004/56649d135503460f949e6a4a/html5/thumbnails/39.jpg)
Friday 2:00-3:00pm Building Websites using VSOnline Monaco Chris Dias
Related Talks
![Page 40: patterns TypeScript size interface IModelChangeAccessor { insertText(position:IPosition, text:string): IEditorPosition; deleteText(range:IRange):](https://reader030.vdocuments.mx/reader030/viewer/2022013004/56649d135503460f949e6a4a/html5/thumbnails/40.jpg)
TypeScript www.typescriptlang.org
AMD http://requirejs.org/docs/whyamd.html
TFS use of TypeScript http://
blogs.msdn.com/b/bharry/archive/2012/10/24/typescript-a-real-world-story-of-adoption-in-tfs.aspx
Monaco VS Online Get started with the Monaco Channel9 Series Keep informed on the Monaco Blog
Resources
![Page 41: patterns TypeScript size interface IModelChangeAccessor { insertText(position:IPosition, text:string): IEditorPosition; deleteText(range:IRange):](https://reader030.vdocuments.mx/reader030/viewer/2022013004/56649d135503460f949e6a4a/html5/thumbnails/41.jpg)
for MSDN Ultimate subscribers
Go to http://msdn.Microsoft.com/specialoffers
SPECIAL OFFERSPartner Program
![Page 42: patterns TypeScript size interface IModelChangeAccessor { insertText(position:IPosition, text:string): IEditorPosition; deleteText(range:IRange):](https://reader030.vdocuments.mx/reader030/viewer/2022013004/56649d135503460f949e6a4a/html5/thumbnails/42.jpg)
Your Feedback is Important
Fill out an evaluation of this session and help shape future events.
Scan the QR code to evaluate this session on your mobile device.
You’ll also be entered into a daily prize drawing!
![Page 43: patterns TypeScript size interface IModelChangeAccessor { insertText(position:IPosition, text:string): IEditorPosition; deleteText(range:IRange):](https://reader030.vdocuments.mx/reader030/viewer/2022013004/56649d135503460f949e6a4a/html5/thumbnails/43.jpg)
© 2014 Microsoft Corporation. All rights reserved. Microsoft, Windows, Windows Vista and other product names are or may be registered trademarks and/or trademarks in the U.S. and/or other countries.The information herein is for informational purposes only and represents the current view of Microsoft Corporation as of the date of this presentation. Because Microsoft must respond to changing market conditions, it should not be interpreted to be a commitment on the part of Microsoft, and Microsoft cannot guarantee the accuracy of any information provided after the date of this presentation. MICROSOFT MAKES NO WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, AS TO THE INFORMATION IN THIS PRESENTATION.