January, 2013

 
  • TypeScript

    Trying the Latest TypeScript Build

    • 10 Comments

    Starting with release 0.8.2.0, you can now update the TypeScript language services file, the compiled JavaScript that powers most of the TypeScript editor features in Visual Studio. This includes tasks like error reporting, compile-on-save, renaming, go to definition, completion lists, signature help, and others.

    By updating your TypeScript language services file, you can try out the latest features we're working on before they appear in an official release. Naturally, you might encounter bugs here as the code built in the development branches isn't as stable or well-tested as the released version.

    The majority of the TypeScript editor features are found in a file called typescriptSerivces.js. To update your file, you'll need to get a new copy and overwrite the existing copy.

    Obtaining a new 'typescriptServices.js' file

    Option 1: Use the LKG

    The LKG ("Last Known Good") version of the compiler is updated somewhat frequently. You can get a copy from CodePlex using the source browser and downloading the typescriptServices.js file from the bin directory.

    Option 2: Build Locally

    Install git and Node.js

    You'll need some basic tools first

    • Install git. Some recommendations for the install options:
      • Don't install the Windows Explorer integration unless you plan to use it
      • Select the Run Git from the Windows Command Prompt option on the following page
      • Select Checkout as-is, commit as-is option on the following page to minimize any line-ending weirdness
    • Install Node.js

    Setup a Local Repository

     > git clone https://git01.codeplex.com/typescript 

    This will set up a TypeScript repository in a subfolder of the current folder called 'typescript'.

    Select a Branch

     > cd typescript > git checkout develop 

    If you're interested in the latest, the develop branch is probably your best bet. There may be other branches with active development; if you know of a branch you'd like to try out instead, replace develop with that branch name.

    Get the Development Dependencies

     > npm install 

    This will install a local copy of jake, the build system we use for TypeScript.

    Build TypeScript

     > .\node_modules\.bin\jake local 

    This will produce built\local\typescriptServices.js. Copy that file as indicated below.

    Iterate

    If you like, you can simply delete the TypeScript folder created in the first step and be done. However, if you come back at a later time and want a new fresh copy (with the latest changes), you'll need to run git pull to get the newest sources. After that, just run jake local and copy over the typeScriptServices.js file again.

    Updating TypescriptServices.js

    You'll need to locate the folder where the TypeScript extension was installed. Look for a file called typescriptServices.js in a folder like:

    C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\Extensions\enn4wcm5.z2b\

    The highlighted portion at the end there will be different on every machine, but there shouldn't be too many of them in the Extensions folder. In some rare cases, you might have more than one subfolder that has a TypeScript installation in it; if this is the case, you'll want to use the newest one (check the Created date).

    When you find the one with typescriptServices.js, backup that file and copy in the new version. After you restart Visual Studio, you'll be working with the updated services file.

  • TypeScript

    Walkthrough: Interfaces

    • 3 Comments

    When we talk about a type in TypeScript, we mean a collection of things that you can do with a variable (or expression). You might be able to read or write a given property, call a function, use the expression as a constructor, or index into the object. Some objects (like Date) in JavaScript can do nearly all of those! In TypeScript, interfaces are the most flexible way of describing types.

    You'll see interfaces used to describe existing JavaScript APIs, create shorthand names for commonly-used types, constrain class implementations, describe array types, and more. While they don't generate any code (and thus have no runtime cost!), they are often the key point of contact between any two pieces of TypeScript code, especially when working with existing JavaScript code or built-in JavaScript objects.

    The only job of an interface in TypeScript is to describe a type. While class and function deal with implementation, interface helps us keep our programs error-free by providing information about the shape of the data we work with. Because the type information is erased from a TypeScript program during compilation, we can freely add type data using interfaces without worrying about the runtime overhead.

    While that sounds like a simple, one-purpose task, interfaces role in describing types becomes manifest in a large variety of ways. Let's look at some of them and how they can be used in TypeScript programs.

    Basics

    To define an interface in TypeScript, use the interface keyword:

    interface Greetable {
        greet(message: string): void;
    }

    This defines a type, Greetable, that has a member function called greet that takes a string argument. You can use this type in all the usual positions; for example in a parameter type annotation. Here we use that type annotation to get type safety on the g parameter:

    function helloEnglish(g: Greetable) {
        g.greet('Hello there!'); // OK
        g.greet(42); // Not OK -- 42 is not a string
        g.greep('Hi'); // Not OK -- 'greep' is not a member of 'Greetable'
    }

    When this code compiles, you won't see any mention of Greetable in the JavaScript code. Interfaces are only a compile-time construct and have no effect on the generated code.

    Interfaces: TypeScript's Swiss Army Knife

    Interfaces get to play a lot of roles in TypeScript code. We'll go into more detail on these after a quick overview.

    Describing an Object

    Many JavaScript functions take a "settings object". For example, jQuery's $.ajax takes an object that can have up to several dozen members that control its behavior, but you're only likely to pass a few of those in any given instance. TypeScript interfaces allow optional properties to help you use these sorts of objects correctly.

    Describing an Indexable Object

    JavaScript freely mixes members (foo.x) with indexers (foo['x']), but most programmers use one or the other as a semantic hint about what kind of access is taking place. TypeScript interfaces can be used to represent what the expected type of an indexing operation is.

    Ensuring Class Instance Shape

    Often, you'll want to make sure that a class you're writing matches some existing surface area. This is how interfaces are used in more traditional OOP languages like C# and Java, and we'll see that TypeScript interfaces behave very similarly when used in this role.

    Ensuring the Static Shape of a Class or Constructor Object

    Interfaces normally describe the shape of an instance of a class, but we can also use them to describe the static shape of the class (including its constructor function). We'll cover this in a later post.

    Describing an Object

    You can also use interfaces to define the shape of objects that will typically be expressed in an object literal. Here's an example:

    Describing Simple Types

    interface ButtonSettings {
        text: string;
        size?: { width: number; height: number; };
        color?: string;
    }

    function createButton(settings: ButtonSettings) { ... }

    Note the use of the ? symbol after some of the names. This marks a member as being optional. This lets callers of createButton supply only the members they care about, while maintaining the constraint that the required parts of the object are present:

    createButton({ text: 'Submit' }); // OK
    createButton({ text: 'Submit', size: { width: 70, height: 30 }}); // OK
    createButton({ text: 'Submit', color: 43); // Not OK: 43 isn't a string
    createButton({ text: 'Submit', size: { width: 70 }); // Not OK: size needs a height as well
    createButton({ color: 'Blue'}); // Not OK: 'text' member is required

    You typically won't use optional members when defining interfaces that are going to be implemented by classes.

    Here's another example that shows an interesting feature of types in TypeScript:

    interface Point {
        x: number;
        y: number;
    }

    function getQuadrant(pt: Point) { ... }

    var pt = { x: 0, y: -1 };
    getQuadrant(pt); // OK: pt has members x and y of type number

    Note that we didn't annotate pt in any way to indicate that it's of type Point. We don't need to, because type checking in TypeScript is structural: types are considered identical if they have the same surface area. Because pt has at least the same members as Point, it's suitable for use wherever a Point is expected.

    Describing External Types

    Interfaces are also used to describe code that is present at runtime, but not implemented in the current TypeScript project. For example, if you open the lib.d.ts file that all TypeScript projects implicitly reference, you'll see an interface declaration for Number:

    interface Number {
        toString(radix?: number): string;
        toFixed(fractionDigits?: number): string;
        toExponential(fractionDigits?: number): string;
        toPrecision(precision: number): string;
    }

    Now if we have an expression of type Number, the compiler knows that it's valid to call toPrecision on that expression.

    Extending Existing Types

    Moreover, interfaces in TypeScript are open, meaning you can add your own members to an interface by simply writing another interface block. If you have an external script that adds members to Date, for example, you simply need to write interface Date { /*...*/ } and declare the additional members.*

    * Note: There are some known issues with the Visual Studio editor that currently prevent this scenario from working as intended. We'll be fixing this limitation in a later release.

    Describing an Indexable Object

    A common pattern in JavaScript is to use an object (e.g. {}) as way to map from a set of strings to a set of values. When those values are of the same type, you can use an interface to describe that indexing into an object always produces values of a certain type (in this case, Widget).

    interface WidgetMap {
        [name: string]: Widget;
    }

    var map: WidgetMap = {};
    map['gear'] = new GearWidget();
    var w = map['gear']; // w is inferred to type Widget

    Ensuring Class Instance Shape

    Let's extend the Greetable example above:

    /** Represents an object that can be greeted */
    interface Greetable {
        /** Used to welcome someone */
        greet(message: string): void;

        /** The preferred language of this object */
        language: string;
    }

    We can implement this interface in a class using the implements keyword:

    class Person implements Greetable {
        language = 'English';

        greet(message: string) {
            console.log(message);
        }
    }

    Now we can use an instance of Person wherever a Greetable is expected:

    var g: Greetable = new Person();

    Similarly, we can take advantage of the structural typing of TypeScript to implement Greetable in an object literal:

    var greeter = {
        greet: (message: string) => { console.log(message) };
        language: 'Any';
    };
  • TypeScript

    Announcing TypeScript 0.8.2

    • 23 Comments

    We’re happy to announce the 0.8.2 preview release of TypeScript.  This release has been focused on  addressing key usability feedback and filling in tooling experiences.  Along the way, we’ve also incorporated some of the highest-rated feature requests and bugfixes.

    JSDoc Support

    Being able to see API documentation comments during Intellisense and parameter help has been a highly requested feature.  In fact, it’s currently the 2nd most-requested feature in the issue tracker.

    With 0.8.2, the TypeScript compiler and tools now support JSDoc comments.

    In the TypeScript implementation, because types are already part of the system, we allow the JSDoc type annotation to be elided, as in the example above.

    You can now document a variety of language constructs (including classes, modules, interfaces, and functions) with comments that become part of the information displayed to the user.  We’ve also started extending lib.d.ts, the default JS and DOM API library, with JSDoc comments.

    This capability is also part of the language service, so cross-platform tools can take advantage of it.

    Compile-on-Save

    Many of the themes in this release center around simplifying workflow.  We’ve focused on a few key areas with the aim of streamlining developing in TypeScript.

    Languages like TypeScript which compile to JavaScript add a build step into the development cycle.  Enabling a compile-on-save mode of use minimizes this overhead by automatically updating the compiled JS when the TypeScript source changes.  With 0.8.2, we’ve done work to further enable this in both the NPM-based compiler and in Visual Studio.

    The 0.8.2 release adds initial support for compile-on-save in Visual Studio.  Just as the name implies, when enabled the project or file being edited will be compiled when the changes are saved.  For more information, please see the wiki page for compile-on-save.

     

    TypeScript supports compile-on-save on the command line using the cross-platform NPM-based TypeScript compiler as well with the improved --watch compiler option.  This option allows a compile to begin watching a set of files.  Once a watched file is changed, the compiler rebuilds the corresponding output for that file.

    Various Improvements

    • We’ve further improved the Visual Studio TypeScript debugging experience in 0.8.2.  The debugger will now honor breakpoints after F5 (refresh) during a debug session.  Combined with the addition of compile-on-save, the workflow to edit and debug a web app is as easy as saving the edited changes and refreshing the browser.
    • It’s possible now to specify output directory when compiling external modules.  This gives a cleaner way to build external modules without having the output in-tree.
    • The compiler service can now be replaced in the TypeScript for Visual Studio 2012 plugin.  This makes it easier to leverage the Visual Studio TypeScript extension with newer compiler builds from CodePlex or from experimental forks.
    • We’ve moved to Jake for building the compiler and language service.  Jake is a simpler solution which should make it easier to work with and build the compiler in a multiplatform-friendly way.
  • TypeScript

    Working on 0.8.2

    • 5 Comments

    We’ve recently branched for the upcoming 0.8.2 release of TypeScript.  Before we talk about what’s new, we wanted to talk a bit about the engineering process that goes into making a release.

    Going forward, TypeScript development will happen across three types of branches.  Our current two branches of 'master' and 'develop' stay, taking the roles of stable and cutting edge development as before.  We're also going to be adding branches for each of the upcoming releases, so that they each release can stabilize.  The current 0.8.2 release is wrapping up, and you can watch the stabilization process by going to the CodePlex repo and selecting "release-0.8.2" in the dropdown.  For more information, there's also a wiki page with more details about the separate branches.

    We’re currently working on the 0.8.x release train, which is focused on addressing key usability feedback and filling in tools experience.  In parallel, design work on the upcoming 0.9.x release train is underway, in which we expect to address some of the larger TypeScript language changes that are under discussion on the TypeScript forums and issue tracker.  More details on early 0.9.x design thinking coming in a future post.

    The 0.8.2 release will include, among other features and bug fixes, these popular requests:

    • We’ve moved our build system for the compiler and language service from nmake to Jake.  This should make it much easier to build TypeScript on non-Windows systems.
    • We’ve simplified and expanded --out, which can now also accept a directory as an argument.  This allows users to target a directory when compiling external modules and should help alleviate a class of issues new users encounter by trying to both using the ‘import’ statement and passing a filename to --out.
    • Our watch functionality (available through --watch) should now be more reliable and work in more situations, allowing a compile-on-save workflow on the commandline when using the npm-based TypeScript compiler.
    • Numerous bugfixes
    • Much more!  We’ll show off more of the new features in the official 0.8.2 release announcement.

    As always, you can follow the work on CodePlex, and share any feedback on the forums and issue tracker.

Page 1 of 1 (4 items)