JsDoc is a great tool for documenting code and providing type-safety in your JavaScript project without any additional configuration. Learn what JsDoc is, how it works, the benefits it provides, and how to use it in your project.
JavaScript is a powerful and flexible language that powers many applications on the internet. It is weakly typed and mostly assumes any
type — pun intended. However, code editors such as VS Code create workflows that provide some level of type-safety while working with JavaScript.
The target of this article is JavaScript developers seeking to add type safety in their project and TypeScript developers as it explores code documentation with JsDoc. This article will discuss JsDoc - the benefits, how it works, inferring types in your code, and type inference with Prisma.
What is JsDoc?
JsDoc is an API documentation generator for JavaScript using multi-line comments. It scans through your code and generates documentation in available in a HTML website. JsDoc is compatible with both JavaScript and TypeScript.
Why use JsDoc?
Improves code documentation
Documenting code is a valuable skill for developers. Documentation provides information for yourself and other developers - by explaining what the code does and how it does it. This makes maintenance and code review simpler and reduces the entry barriers for other contributors to your code.
JsDoc improves code documentation in a more structured manner using tags to describe arguments, return values, namespaces, modules, etc.
Library authors take advantage of JsDoc to provide as much detail as possible, for example, on types, code examples/ mini-tutorials, and utility functions. An example of well-documented libraries are Nexus.
Provides type safety
A weakness JavaScript is known for is having a weak type system. JsDoc provides a way to infer types in your JavaScript project.
Having types improves code maintainability, speeds up refactoring, reduces guesswork trying to understand code, and could possibly save you hours of debugging typos, undeclared variables, and undefined
types.
JsDoc paired with VS Code provides rich intellisense that boosts developer productivity.
Compatible with JavaScript and TypeScript
JsDoc is works seamlessly with both JavaScript and TypeScript. The types declared via JsDoc serve as a form of API documentation for your code. JsDoc can also be paired with TypeScript, making your code as descriptive as possible.
How does JsDoc work?
Under the hood of VS Code is the JavaScript Language Service that provides intellisense when working with JavaScript. The language service analyzes types from three different sources to provide great developer experience:
- Implicitly inferring types from your code based on usage
- TypeScript declaration files
- JsDoc
VS Code ships with JsDoc support and therefore requires no set up to get started. You can configure VS Code to check types in your JavaScript project in the following ways:
- Adding
@ts-check
at the top of every file. - Modifying the following setting:
"js/ts.implicitProjectConfig.strictFunctionTypes": true
- Using
jsconfig.json
ortsconfig.json
by adding the"checkJs": true
in thecompilerOptions
configuration - Explicitly specifying types using JsDoc
If you're working on VS Code, either of the would work just fine for any project. These options complement each other and it's up to you to choose what works better for you.
Fun fact: The former code name of the JavaScript Language Server was Salsa.
The fundamental element needed to document code using JsDoc is a tag. JsDoc provides two types of tags: block tags and inline tags.
Block tags provide means to annotate variables, functions, arguments, modules, namespaces, return types, and classes and describe what a specific code snippet does. These could be types, arguments, callbacks, modules, namespaces, etc. Inline tags are used to link to other parts of the documentation.
To get started with JsDoc, add an annotation before blocks of code. The annotations are captured between multi-line comments - /** */
- and use JsDoc's block tags, for example @type
.
The annotations are picked up by the JavaScript Language service and infer types in your project. You can then preview the docs by hovering on the snippets of code, for example functions and variables. Besides documenting the code, JsDoc also adds type-safety to your application.
Example block tags that can be used to add types to your code are @type
, @typedef
, @params
and @returns
.
Working with types
JavaScript's primitive type types are supported in JsDocs. More advanced TypeScript types can be used in your project as well. Some of the example types this article will explore include:
Primitive types
/** * @type {string} */let firstName;
Structural types
/** * @type {{name: string, age: number, isOk: boolean}} */let user;
Nullable types
/** * @type{?string} userName */let userName;
Built-in objects
JsDoc allows you to reference the standard built-in objects in JavaScript such as Promise
, Document
, Window
etc.
/** * @type {Document} */let document;
Union Types
/** * @type {"asc"| "desc"} orderBy */let orderBy;
Generic Types
/** * @template D * @param {D} data * @return {D} data*/const createData = (data) => { return data };
Type inference with Prisma
Prisma is a database ORM that provides developers with a type-safe database client. Prisma provides an intuitive API that makes modelling and querying data fun for all developers. Currently, Prisma supports PostgreSQL, MySQL, SQLite, SQL Server and MongoDB preview.
Initialize your project
Create a project directory and navigate into it:
mkdir awesome-project # Give your project a memorable namecd awesome-projectCopy
Next, install Prisma CLI as a development dependency and Prisma client:
npm init -ynpm install -D prismanpm install @prisma/clientCopy
The Prisma CLI is as a development dependency used for the following:
- Initializing Prisma in your project
- Running database migrations
- Generating Prisma Client
- Managing the database schema and lifecycle
- Introspecting your existing database.
- Opening Prisma Studio - a database GUI for interacting with data
Prisma Client is the database client for querying data in your JavaScript or TypeScript application. Initialize Prisma in your project:
npx prisma initCopy
This command does the following creates:
- A folder called
prisma
at the root of your project - A
.env
file at the root of your project - A
schema.prisma
file. You will define your database models here.
Connect to your database
To connect to your database, set the url
field in the datasource
block in your Prisma schema to the connection URL pointing to your database. For simplicity, this guide will use SQLite.
datasource db {provider = "sqlite"url = "file:./dev.db"}generator client {provider = "prisma-client-js"}model Post {id Int @id @default(autoincrement())title Stringcontent String?}Copy
With your database models set up, run the command to create the database and the table as well.
npx prisma migrate dev --name initCopy
This creates and applies a database migration against your database. A SQLite database is also created in the prisma
directory. Prisma CLI generates the Prisma Client for you after a successful migration.
Assuming you have the following Prisma schema in your project:
datasource db {provider = "sqlite"url = "file:./dev.db"}generator client {provider = "prisma-client-js"}model Post {id Int @id @default(autoincrement())title Stringcontent String?}Copy
In a JavaScript file within your project add the following:
/*** @typedef { import("@prisma/client").Post } Post* @typedef { import("@prisma/client").Prisma.PostCreateInput } postCreateInput*/const { PrismaClient } = require("@prisma/client");const prisma = new PrismaClient()/*** This function creates one post record* @param {postCreateInput} data* @returns {Promise<Post>} post*/const createOnePost = async (data) => {return await prisma.post.create({data})}Copy
Hovering on the function declaration, function arguments, the data
property will bring up the different types and descriptions referenced in the code. The types generated by the Prisma CLI are TypeScript types derived from your models. They are imported using the TypeScript syntax.
Explore the Prisma Client type-definitions by hovering on the imported type, for example
PostCreateInput
, pressingCtrl
orCmd
and left clicking on it.
Learn more about Productive Development With Prisma's Zero-Cost Type Safety and the Learn TypeScript: A Pocketguide Tutorial.
Conclusion
In summary, JsDoc makes a great tool for code documentation and provide a level of type safety when working with JavaScript. JsDoc also provides an incremental way of adopting types in your application without migrating your codebase to TypeScript.
If you have any questions regarding JsDoc, type safety, code documentation or Prisma, feel free to reach out to us on Twitter, ask a question on GitHub or send us a message on Slack.