Frontend Development 31 min read

How to Get Full TypeScript IntelliSense in Plain JavaScript with VSCode

This tutorial explains how to bring TypeScript‑style type checking and autocomplete into regular JavaScript files using VSCode, JSDoc comments, and declaration files, allowing developers to enjoy static‑type benefits without converting the whole project to .ts files.

WecTeam
WecTeam
WecTeam
How to Get Full TypeScript IntelliSense in Plain JavaScript with VSCode

Preface

Many TypeScript fans sigh that they want to use TS but are forced to write plain JavaScript. This article shows that you can work fluently with TypeScript features inside JavaScript, and your manager won’t complain.

Written Up Front

Previous article: TS Advocacy Guide [1]

After reading the previous guide, many commenters said, “TS is great, but our boss doesn’t care.” This sequel explains the results of my long‑term experiments with using TypeScript inside JavaScript.

If you already know TS, the article will be smooth; if not, you can still follow along, and if you dislike TS, just treat it as a fun read.

The article targets the latest VSCode (v1.41.0). Other IDEs may behave differently.

WebStorm also supports these features, but because it has its own intelligent engine, it is not discussed here.

What? You still use Notepad?

How It Works

TypeScript Inside VSCode

TypeScript was released by Microsoft in 2012 but did not gain much attention in China before VSCode existed. Some developers recognized its potential to fix JavaScript’s weaknesses and started using it, especially those with backend backgrounds who preferred static typing and IDEs like Visual Studio or Eclipse that already supported TS.

When VSCode appeared, it became a lightweight IDE for front‑end developers, and TS adoption surged. Even when you write plain JavaScript, VSCode can provide TypeScript‑powered suggestions automatically.

TypeScript Inside JavaScript

Ever wondered why typing

document.

in a JS file triggers a popup of all DOM methods? That’s because VSCode bundles the TypeScript library, which includes declaration files such as

lib.dom.d.ts

that describe DOM APIs.

The file lists many familiar method names, providing DOM‑related IntelliSense for plain JavaScript.

In JavaScript, the scope of TypeScript usage is actually broader than you might think.

Elegant Declaration Files

Let’s talk about the

.d.ts

declaration files that give you type hints.

Built‑in Declaration Files

VSCode ships a

node_modules

folder that contains the TypeScript package and a set of basic

.d.ts

files. To enable newer ECMAScript features, create a

jsconfig.json

in the project root:

<code>{
  "compilerOptions": {
    "lib": ["dom", "esnext"]
  }
}
</code>

Now you can enjoy ES2020 syntax suggestions.

Package‑Provided Declaration Files

Some packages ship their own declaration files. For example,

@types/node

provides Node.js APIs. Install it with:

<code>npm i @types/node -D
</code>

Now you get intelligent hints for Node.js globals.

Global Variables

Front‑end teams often attach utilities to

window

. By writing a declaration file you can make those globals typed:

<code>interface ILib {
  /** Get current environment */
  getEnv: string;
  /** Image methods */
  img: {
    formatImg: (a: string, b: string) => string;
  };
  /** URL methods */
  url: {
    formatUrl: (a: string) => string;
  };
}

declare var XXCompanyLib: ILib;
</code>

Magic Comments – JSDoc

Standard JavaScript comments (

//

and

/* */

) are familiar, but JSDoc (

/** */

) can embed type information directly in JS files.

<code>/**
 * Method: foo
 * @param {string} name
 */
function foo(name) {
  console.log(name);
}
</code>

What JSDoc Solves

When a function’s parameters lack type annotations, the IDE treats them as

any

, causing loss of type safety. Adding JSDoc @param tags tells VSCode the expected types, and the return type can be inferred.

<code>function foo(a, b) {
  console.log(a);
  console.log(b);
  return a; // return any
}
var bar = foo(1, 2); // bar is any
</code>

After adding JSDoc:

<code>/**
 * @param {string} name
 * @returns {string}
 */
function foo(name) {
  return name;
}
var bar = foo('test'); // bar is string
</code>

Advanced Tags

Beyond @param and @return, JSDoc supports @typedef and @property to describe complex objects.

<code>/**
 * @typedef {Object} IAjaxOptions
 * @property {boolean} [jsonp]
 * @property {boolean} [async]
 * @property {'GET'|'POST'} [methods]
 * @property {function(options:any):void} [success]
 */
/**
 * @param {string} url
 * @param {IAjaxOptions} [options]
 */
function ajaxNew(url, options) {}
</code>

Don’t Overuse

Using JSDoc everywhere can become noisy and hard to maintain. It’s best for frequently used APIs or shared utilities.

Manual annotation can be time‑consuming.

Inconsistent documentation leads to confusion.

Incorrect @type can hide real bugs.

VSCode’s JSDoc support is still limited for complex types.

When possible, migrate the codebase to real

.ts

files for full type safety.

Practical Recommendations

Fix the Root Cause First

VSCode can infer many types automatically if the code is written clearly. For example, instead of adding a property after object creation, define it upfront:

<code>var foo = { a: 1, b: 2 };
// IDE now knows foo.a and foo.b
</code>

Use typeof in JSDoc

When you want a function to accept an object with the same shape as an existing variable, use

{@type {typeof foo}}

:

<code>/** @param {typeof foo} obj */
function bar(obj) {
  obj.a; // jumps to foo.a definition
}
</code>

Enable // @ts-check

Adding

// @ts-check

at the top of a JS file makes VSCode treat the file as if it were TypeScript, reporting type errors.

Annotate Frequently Used Objects

For global utilities like

zepto

, create a typedef that re‑exports the type:

<code>/** @typedef {typeof $} ZeptoStatic */
/** @type {ZeptoStatic} */
var $ = require('zepto');
</code>

Using TypeScript in Vue

Vue already ships

vue.d.ts

. By importing the type of the component options you can get full IntelliSense without changing the file extension.

<code>/** @type {import('vue').ComponentOptions} */
const options = {
  name: 'app',
  data() { return { shareDialog: false }; },
  methods: {
    click() { console.log(123); }
  }
};
</code>

Advanced Practices

TS in JS with JSDoc – Merging Objects

Use @returns to describe the combined type of two objects:

<code>/**
 * Merge two scopes
 * @returns {{...typeof args &amp; typeof fn}}
 */
function someMergeFn(args, fn) {
  // ...implementation
}
const newObj = someMergeFn(args, fn);
newObj.a; // jumps to args.a
newObj.bar; // jumps to fn.bar
</code>

Re‑exporting Types from Other Files

When a module returns an object without a proper export, you can annotate the import:

<code>/** @type {import('./otherService')} */
var newObj = someRequireFn('./otherService');
newObj.a; // jumps to otherService.js args.a
newObj.bar; // jumps to otherService.js fn.bar
</code>

Combining Declaration Files and JSDoc

Create a custom

.d.ts

that describes a complex shape, then reference it from JSDoc:

<code>// InterfaceJs.d.ts
export interface INewObj {
  a: number;
  b: number;
  foo(): void;
  bar(): void;
}
/** @type {import('./InterfaceJs').INewObj} */
var newObj = someRequireFn('./otherService');
newObj.a; // jumps to INewObj definition
</code>

Conclusion

There are two main ways to bring TypeScript capabilities into JavaScript:

Use declaration (

.d.ts

) files.

Write JSDoc comments.

Both can be combined for more complex scenarios. Apply them to shared components, global variables, and frequently used functions to get reliable IntelliSense without a full migration to TypeScript.

How to Apply

Write declaration files for public components and globals.

Add JSDoc to custom functions and keep them tidy.

Use

@type

to give explicit types to ambiguous variables.

Precautions

Don’t overuse JSDoc; it can become a maintenance burden.

Prefer “jump‑to‑definition” over artificial type casts.

If you want to try the demos locally, clone the repository linked below and open the files in VSCode.

References

[1]

TS Advocacy Guide – https://juejin.im/post/5d8efeace51d45782b0c1bd6

[2]

Same as above.

[3]

Demo repository – https://github.com/Lienviws/TS_in_JS_DEMO

[4]

Module resolution – https://www.tslang.cn/docs/handbook/module-resolution.html

[5]

Type search – https://microsoft.github.io/TypeSearch/

[6]

DefinitelyTyped – https://github.com/DefinitelyTyped/DefinitelyTyped/

[7]

Declaration files guide – https://ts.xcatliu.com/basics/declaration-files

[8]

JSDoc @param – https://jsdoc.app/tags-param.html

[9]

JSDoc @type – https://jsdoc.app/tags-type.html

[10]

JSDoc @typedef – https://jsdoc.app/tags-typedef.html

[11]

JSDoc homepage – https://jsdoc.app/index.html

[12]

Demo repo – https://github.com/Lienviws/TS_in_JS_DEMO

[13]

Official site – https://wecteam.io/

frontendTypeScriptJavaScriptvscodeJSDoctype declarations
WecTeam
Written by

WecTeam

WecTeam (维C团) is the front‑end technology team of JD.com’s Jingxi business unit, focusing on front‑end engineering, web performance optimization, mini‑program and app development, serverless, multi‑platform reuse, and visual building.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.