Type Checking in VS Code Without TypeScript

But how, you ask

Jay Kariesch
Better Programming

--

Photo by Blake Wisz on Unsplash

Preface

When starting a new team project, the mention of TypeScript can be intimidating, especially to those who are new to the concept of typed languages.

I’d be lying if I said I didn’t get it. It’s a development dependency that infects your entire text editor — it underlines seemingly random function calls and variables in red; fills VS Code hints with cryptic sounding warnings, and interfaces, unions, and enums? Oh my!

It’s a big commitment to push onto a team that has little-to-no TypeScript experience, but lucky for us there’s a way to include some of the value TypeScript delivers without installing any development dependencies — or forcing an entire team to commit to a scary superset of JavaScript.

But How?

TypeScript language features are actually built into VS Code. Don’t believe me? Check this out:

Built-in TypeScript language features

The marriage of VS Code + JSDoc + TypeScript allows us to express types through JSDoc annotations, and enforce type checking with TypeScript inside a Vanilla JavaScript file. This is covered in VS Code’s official documentation.

Getting Started

What you’ll need for this tutorial:

  • VS Code
  • React (Optional as these principals can be applied to any JS.)

Awesome. Now, let’s create our first document — a card component (Card.jsx)!

Let’s import the card into App.jsx:

When you hover over <Card/>, VS Code should automatically generate a hint containing an inferred function signature, like this:

There are two things to note:

  1. The editor didn’t provide any feedback indicating <Card/> requires props.
  2. The property types for props are any.

Type Inference

There are various ways to enhance type inference.

ES6 default parameters (not to be confused with Component.defaultProps):

Default parameters apply required properties to your function signature.

This means that when type checking is enabled, the <Card/> component will be underlined in red to indicate props are required, and the hint will tell you exactly what is needed.

Destructured defaults:

Destructured defaults are interpreted as optional parameters. This can be verified by enabling type checking — you’ll notice that <Card/> is not underlined.

And finally, JSDoc annotations:

The advantage of JSDoc annotations is how explicit type definitions can be.

It’s TypeScript’s backdoor into your JavaScript application via VS Code — meaning annotating with types and documenting your signatures is nearly the same as writing types and interfaces and documenting signatures in TypeScript.

Where they’re written and how is a bit different.

Type Checking

Hints and annotations are great, but to further idiot-proof our application, let’s kick it up a notch and enable the dreaded red underline.

Type checking per document

In App.jsx, add the following to the top of the document:

// @ts-check

This enables TypeScript to provide visual feedback when it discovers an issue, like this:

In my example, <Card/> is using JSDoc annotations. Let’s take a look at the hint:

Let’s fix this error:

Type checking workspace

// @ts-check can be tedious. What if we wanted type checking to persist throughout the entire workspace without adding // @ts-check to the top of each document?

Create the following directory + file:

.vscode -> settings.json

Inside of settings.json, add the following:

{
"javascript.implicitProjectConfig.checkJs": true
}

Type checking should now occur throughout your project.

Additional Advice

When using JSDoc, common typedefs can be defined at the top of a document and re-used, like this:

Thanks for reading. I hope you found this helpful!

--

--