JavaScript and TypeScript in Visual Studio

Applies to: yesVisual Studio noVisual Studio for Mac

Overview

Visual Studio 2022 provides rich support for JavaScript development, both using JavaScript directly, and also using the TypeScript programming language, which was developed to provide a more productive and enjoyable JavaScript development experience, especially when developing projects at scale. You can write JavaScript or TypeScript code in Visual Studio for many application types and services.

JavaScript Language Service

The JavaScript experience in Visual Studio 2022 is powered by the same engine that provides TypeScript support. This engine gives you better feature support, richness, and integration immediately out-of-the-box.

The option to restore to the legacy JavaScript language service is no longer available. Users have the new JavaScript language service out-of-the-box. The new language service is solely based on the TypeScript language service, which is powered by static analysis. This service enables us to provide you with better tooling, so your JavaScript code can benefit from richer IntelliSense based on type definitions. The new service is lightweight and consumes less memory than the legacy service, providing you with better performance as your code scales. We also improved performance of the language service to handle larger projects.

TypeScript support

By default, Visual Studio 2022 provides language support for JavaScript and TypeScript files to power IntelliSense without any specific project configuration.

For compiling TypeScript, Visual Studio gives you the flexibility to choose which version of TypeScript to use on a per-project basis.

In MSBuild compilation scenarios, the TypeScript NuGet package is the recommended method of adding TypeScript compilation support to your project. Visual Studio will give you the option to add this package the first time you add a TypeScript file to your project. This package is also available at any time through the NuGet package manager. When the NuGet package is used, the corresponding language service version will be used for language support in your project. Note: The minimum supported version of this package is 3.6.

Projects configured for npm can specify their own version of the TypeScript language service by adding the TypeScript npm package. You can specify the version using the npm manager in supported projects. Note: The minimum supported version of this package is 2.1.

The TypeScript SDK has been deprecated in Visual Studio 2022. Existing projects that rely on the SDK should be upgraded to using the NuGet package. For projects that cannot be upgraded immediately, the SDK is still available on the Visual Studio Marketplace and as an optional component in the Visual Studio installer.

Tip

For projects developed in Visual Studio 2022, we encourage you to use the TypeScript NuGet or the TypeScript npm package for greater portability across different platforms and environments. For more information, see Compile TypeScript code using NuGet and Compile TypeScript code using tsc.

Project Templates

Starting in Visual Studio 2022, there is a new JavaScript/TypeScript project type (.esproj) that allows you to create standalone Angular, React, and Vue projects in Visual Studio. These front-end projects are created using the framework CLI tools you have installed on your local machine, so the version of the template is up to you.

Within these new projects, you can run JavaScript and TypeScript unit tests, easily add and connect ASP.NET Core API projects and download your npm modules using the npm manager. Check out some of the quickstarts and tutorials to get started. For more information, see Visual Studio tutorials | JavaScript and TypeScript.

Overview

Visual Studio 2019 provides rich support for JavaScript development, both using JavaScript directly, and also using the TypeScript programming language, which was developed to provide a more productive and enjoyable JavaScript development experience, especially when developing projects at scale. You can write JavaScript or TypeScript code in Visual Studio for many application types and services.

JavaScript Language Service

The JavaScript experience in Visual Studio 2019 is powered by the same engine that provides TypeScript support. This gives you better feature support, richness, and integration immediately out-of-the-box.

The option to restore to the legacy JavaScript language service is no longer available. Users now have the new JavaScript language service out-of-the-box. The new language service is solely based on the TypeScript language service, which is powered by static analysis. This enables us to provide you with better tooling, so your JavaScript code can benefit from richer IntelliSense based on type definitions. The new service is lightweight and consumes less memory than the legacy service, providing you with better performance as your code scales. We also improved performance of the language service to handle larger projects.

TypeScript support

Visual Studio 2019 provides several options for integrating TypeScript compilation into your project:

  • The TypeScript NuGet package. When the NuGet package for TypeScript 3.2 or higher is installed into your project, the corresponding version of the TypeScript language service gets loaded in the editor.
  • The TypeScript npm package. When the npm package for TypeScript 2.1 or higher is installed into your project, the corresponding version of the TypeScript language service gets loaded in the editor.
  • The TypeScript SDK, available by default in the Visual Studio installer, as well as a standalone SDK download from the VS Marketplace.

Tip

For projects developed in Visual Studio 2019, we encourage you to use the TypeScript NuGet or the TypeScript npm package for greater portability across different platforms and environments. For more information, see Compile TypeScript code using NuGet and Compile TypeScript code using tsc.

Projects

UWP JavaScript apps are no longer supported in Visual Studio 2019. You cannot create or open JavaScript UWP projects (files with extension .jsproj). You can learn more using our documentation on creating Progressive Web Apps (PWAs) that run well on Windows.

JavaScript is a first-class language in Visual Studio 2017. You can use most or all of the standard editing aids (code snippets, IntelliSense, and so on) when you write JavaScript code in the Visual Studio IDE. You can write JavaScript code for many application types and services.

Note

We have joined the community-wide effort to make MDN web docs the web's one-stop, premiere development resource, by redirecting all (500+ pages) of Microsoft's JavaScript API reference from docs.microsoft.com to their MDN counterparts. For details, see this announcement.

Support for ECMAScript 2015 (ES6) and beyond

Visual Studio now supports syntax for ECMAScript language updates such as ECMAScript 2015/2016.

What is ECMAScript 2015?

JavaScript is still evolving as a programming language and TC39 is the committee responsible for making updates. ECMAScript 2015 is an update to the JavaScript language that brings helpful new syntax and functionality. For a deep dive on ES6 features, check out this reference site.

In addition to support for ECMAScript 2015, Visual Studio also supports ECMAScript 2016 and will have support for future versions of ECMAScript as they are released. To keep up with TC39 and the latest changes in ECMAScript, follow their work on GitHub.

Transpile JavaScript

A common problem with JavaScript is that you want to use the latest ES6+ language features because they help you be more productive, but your runtime environments (often browsers) don't yet support these new features. This means that you either have to keep track of which browsers support what features (which can be tedious), or you need a way to convert your ES6+ code into a version that your target runtimes understand (usually ES5). Converting your code to a version that the runtime understands is commonly referred to as "transpiling".

One of the key features of TypeScript is the ability transpile ES6+ code to ES5 or ES3 so that you can write the code that makes you most productive, but still run your code on any platform. Because JavaScript in Visual Studio 2017 uses the same language service as TypeScript, it too can take advantage of ES6+ to ES5 transpilation.

Before transpilation can be set up, some understanding of the configuration options is required. TypeScript is configured via a tsconfig.json file. In the absence of such a file, some default values are used. For compatibility reasons, these defaults are different in a context where only JavaScript files (and optionally .d.ts files) are present. To compile JavaScript files, a tsconfig.json file must be added, and some of these options must be set explicitly.

The required settings for the tsconfig file are as follows:

  • allowJs: This value must be set to true for JavaScript files to be recognized. The default value is false, because TypeScript compiles to JavaScript, and the compiler should not include files it just compiled.
  • outDir: This value should be set to a location not included in the project, in order that the emitted JavaScript files are not detected and then included in the project (see exclude).
  • module: If using modules, this setting tells the compiler which module format the emitted code should use (for example commonjs for Node, or bundlers such as Browserify).
  • exclude: This setting states which folders not to include in the project. The output location, as well as non-project folders such as node_modules or temp, should be added to this setting.
  • enableAutoDiscovery: This setting enables the automatic detection and download of definition files as outlined previously.
  • compileOnSave: This setting tells the compiler if it should recompile any time a source file is saved in Visual Studio.
  • typeAcquisition: This set of settings control the behavior of automatic type acquisition (further explain in this section)

In order to convert JavaScript files to CommonJS modules and place them in an ./out folder, you could use the following tsconfig.json file:

{
  "compilerOptions": {
    "module": "commonjs",
    "allowJs": true,
    "outDir": "out"
  },
  "exclude": [
    "node_modules",
    "wwwroot",
    "out"
  ],
  "compileOnSave": true,
  "typeAcquisition": {
    "enable": true
  }
}

With the settings in place, if a source file (./app.js) existed and contained several ECMAScript 2015 language features as follows:

import {Subscription} from 'rxjs/Subscription';  // ES6 import

class Foo {  // ES6 Class
    sayHi(name) {
        return `Hi ${name}, welcome to Salsa!`;  // ES6 template string
    }
}

export let sqr = x => x * x;  //ES6 export, let, and arrow function
export default Subscription;  //ES6 default export

Then a file would be emitted to ./out/app.js targeting ECMAScript 5 (the default) that looks something like the following:

"use strict";
var Subscription_1 = require('rxjs/Subscription');
var Foo = (function () {
    function Foo() {
    }
    Foo.prototype.sayHi = function (name) {
        return "Hi " + name + ", welcome to Salsa!";
    };
    return Foo;
}());
exports.sqr = function (x) { return x * x; };
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = Subscription_1.Subscription;

Better IntelliSense

JavaScript IntelliSense in Visual Studio 2017 will now display a lot more information on parameters and member lists. This new information is provided by the TypeScript language service, which uses static analysis behind the scenes to better understand your code. You can read more about the new IntelliSense experience and how it works here.

JSX syntax support

JavaScript in Visual Studio 2017 has rich support for the JSX syntax. JSX is a syntax set that allows HTML tags within JavaScript files.

The following illustration shows a React component defined in the comps.tsx TypeScript file, and then this component being used from the app.jsx file, complete with IntelliSense for completions and documentation within the JSX expressions. You don't need TypeScript here, this specific example just happens to contain some TypeScript code as well.

JSX syntax

Note

To convert the JSX syntax to React calls, the setting "jsx": "react" must be added to the compilerOptions in the tsconfig.json file.

The JavaScript file created at `./out/app.js' upon build would contain the code:

"use strict";
var comps_1 = require('./comps');
var x = React.createElement(comps_1.RepoDisplay, {description: "test"});

Configure your JavaScript project

The language service is powered by static analysis, which means it analyzes your source code without actually executing it in order to return IntelliSense results and provide other editing features. Therefore, the larger the quantity and size of files that are included in your project context, the more memory and CPU will be used during analysis. Because of this, there are a few default assumptions that are made about your project shape:

  • package.json and bower.json list dependencies used by your project and by default are included in Automatic Type Acquisition (ATA)
  • A top level node_modules folder contains library source code and its contents are excluded from the project context by default
  • Every other .js, .jsx, .ts, and .tsx file is possibly one of your own source files and must be included in project context

In most cases, you will be able to just open your project and have great experience using the default project configuration. However, in projects that are large or have different folder structures, it may be desirable to further configure the language service to better focus only on your own source files.

Override defaults

You can override the default configuration by adding a tsconfig.json file to your project root. A tsconfig.json has several different options that can manipulate your project context. A few of them are listed below, but for a full set of all options available, see the schema store.

Important tsconfig.json options

{
  "compilerOptions": {
    "allowJs": true,          // include .js and .jsx in project context (defaults to only .ts and .tsx)
    "noEmit": true            // turns off downlevel compiler
  },
  "files": [],                // list of explicit files to include in the project context. Highest priority.
  "include": [],              // list of folders or glob patterns to include in the project context.
  "exclude": [],              // list of folders or glob patterns to exclude. Overridden by files array.
  "typeAcquisition": {
    "enable": true,           // Defaulted to "false" with a tsconfig. Enables better IntelliSense in JS.
    "include": [ "jquery" ],  // Specific libs to fetch .d.ts files that weren't picked up by ATA
    "exclude": [ "node" ]     // Specific libs to not fetch .d.ts files for
  }
}

Example project configuration

Given a project with the following setup:

  • project's source files are in wwwroot/js
  • project's lib files are in wwwroot/lib
  • bootstrap, jquery, jquery-validation, and jquery-validation-unobtrusive are listed in the bower.json
  • kendo-ui has been manually added to the lib folder

Folder structure

You could use the following tsconfig.json to make sure the language service only analyzes your source files in the js folder, but still fetches and uses .d.ts files for the libraries in your lib folder.

{
  "compilerOptions": {
    "allowJs": true,
    "noEmit": true
  },
  "exclude": ["wwwroot/lib"],  //ignore lib folders, we will get IntelliSense via ATA
  "typeAcquisition": {
    "enable": true,
    "include": [ "kendo-ui" ]  //kendo-ui wasn't added via bower, so we need to list it here
  }
}

Troubleshooting The JavaScript language service has been disabled for the following project(s)

When you open a JavaScript project that has a very large amount of content, you might get a message that reads "The JavaScript language service has been disabled for the following project(s)". The most common reason for having a very large amount of JavaScript source is due to including libraries with source code that exceeds a 20MB project limit.

A simple way to optimize your project is to add a tsconfig.json file in your project root to let the language service know which files are safe to ignore. Use the sample below to exclude the most common directories where libraries are stored:

{
  "compilerOptions": {
    "allowJs": true,
    "allowSyntheticDefaultImports": true,
    "maxNodeModuleJsDepth": 2,
    "noEmit": true,
    "skipLibCheck": true
  },
  "exclude": [
    "**/bin",
    "**/bower_components",
    "**/jspm_packages",
    "**/node_modules",
    "**/obj",
    "**/platforms"
  ]
}

Add more directories as you see fit. Some other examples include "vendor" or "wwwroot/lib" directories.

Note

The compiler property disableSizeLimit can be used as well to disable the 20MB check limit. Take special precautions when using this property because disabling the limit might crash the language service.

Notable Changes from Visual Studio 2015

As Visual Studio 2017 features a completely new language service, there are a few behaviors that will be different or absent from the previous experience. The most notable changes are the replacement of VSDoc with JSDoc, the removal of custom .intellisense.js extensions, and limited IntelliSense for specific code patterns.

No more ///<references/> or _references.js

Previously it was fairly complicated to understand at any given moment which files were in your IntelliSense scope. Sometimes it was desirable to have all your files in scope and other times it wasn't, and this led to complex configurations involving manual reference management. Going forward you no longer need to think about reference management and so you don't need triple slash references comments or _references.js files.

See the JavaScript IntelliSense page for more info on how IntelliSense works.

VSDoc

XML documentation comments, sometimes referred to as VSDocs, could previously be used to decorate your source code with additional data that would be used to buff up IntelliSense results. VSDoc is no longer supported in favor of JSDoc which is easier to write and the accepted standard for JavaScript.

.intellisense.js extensions

Previously, you could author IntelliSense extensions which would allow you to add custom completion results for third-party libraries. These extensions were fairly difficult to write and installing and referencing them was cumbersome, so going forward the new language service won't support these files. As an easier alternative, you can write a TypeScript definition file to provide the same IntelliSense benefits as the old .intellisense.js extensions. You can learn more about declaration (.d.ts) file authoring here.

Unsupported patterns

Because the new language service is powered by static analysis rather than an execution engine (read this issue for information of the differences), there are a few JavaScript patterns that no longer can be detected. The most common pattern is the "expando" pattern. Currently the language service cannot provide IntelliSense on objects that have properties tacked on after declaration. For example:

var obj = {};
obj.a = 10;
obj.b = "hello world";
obj. // IntelliSense won't show properties a or b

You can get around this by declaring the properties during object creation:

var obj = {
    "a": 10,
    "b": "hello world"
}
obj. // IntelliSense shows properties a and b

You can also add a JSDoc comment as follows:

/**
 * @type {{a: number, b: string}}
 */
var obj = {};
obj.a = 10;
obj.b = "hello world";
obj. // IntelliSense shows properties a and b