From JSDoc to TypeScript:

Elevating code documentation and enhancing developer experience.

JSDoc: Structuring creativity

JavaScript, a language of freedom, where creativity knows no bounds 😆

Let's channel this creativity with JSDoc for clarity and guidance 🤓

# CHAPTER 1

What is JSDoc?

  • JSDoc is a markup language for documenting JavaScript code.
  • Allows generation of HTML documentation from source code comments.
  • Supports tags to detail code's structure, purpose, and behavior.
  • Enhances readability, maintainability, and collaboration among developers.
  • Facilitates code insights in IDEs and supports type checking.

The Significance of JSDoc

Facilitating Onboarding

Accelerates the onboarding process for new developers, enabling them to grasp the functionality and architecture of large-scale JavaScript projects rapidly.

1.

2.

Enhancing Team Collaboration

Fosters better understanding and collaboration within development teams.

3.

Sustainable Development
Supports long-term project sustainability by making the codebase more navigable and easier to maintain, even as team members change over time.

# CHAPTER 1
// Normal Javascript Comment 1
/* Normal Javascript Comment 2 */ 

/** 
 JSDoc containing two asterisks
  */
# PRESENTING CODE

JSDoc comment

Two types of tags

# CHAPTER 1
  • Block Tags: Sit at the top level of a JSDoc comment. Start with @ and are followed by a newline, except for the last block tag in a comment.
     
  • Inline Tags: Embedded within the text of a block tag or description. Begin with @ and are enclosed in curly braces {}. Use a backslash \ to escape curly braces within the tag text. Newlines are not required after inline tags.
/**
 * @type {number}
 */
var FOO = 1



/**
 * @const {number}
 */
const FOO = 1

/** 
 * @type {Array<string>}
 */
const colours = ['red', 'blue', 'green']
# JSDoc cheatsheet

Variables

/**
 * This is a function.
 *
 * @param {string} n - A string param
 * @param {string} [o] - A optional string param
 * @param {string} [d=DefaultValue] - A optional string param
 * @return {string} A good string
 *
 * @example
 *
 *     foo('hello')
 */

function foo(n, o, d) {
  return n
}
# JSDoc cheatsheet

Functions

# JSDoc cheatsheet

Types

/**
 * A song
 * @typedef {Object} Song
 * @property {string} title - The title
 * @property {string} artist - The artist
 * @property {number} year - The year
 */



/**
 * Plays a song
 * @param {Song} song - The {@link Song} to be played
 */

function play(song) {}
# JSDoc cheatsheet

Typedef

/**
 * A song
 * @typedef {{
 *   title: string,
 *   artist: string,
 *   year: number
 * }} Song
 */


/**
 * Plays a song
 * @param {Song} song - The {@link Song} to be played
 */

function play(song) {}
# JSDoc cheatsheet

Typedef Shorthand

/**
 * @typedef {import('./Foo').default} Bar
 */

/**
 * @param {Bar} x
 */

function test(x) {}
# JSDoc cheatsheet

Importing types

/**
 * Adds two numbers
 * @param {number} a - The first number
 * @param {number} b - The second number
 */
function add(a, b) {
  return a + b;
}

/**
 * @param {number} a - The first number
 * @param {number} b - The second number
 * @description Adds two numbers
 */
function add(a, b) {
  return a + b;
}
# JSDoc cheatsheet

Tag @description

// The @param tag is used to specify the name (required),
// type, and description of a function's parameter.
// The syntax is:
// @param {Type} Name - Description.
// The parameter type can be a native JavaScript type,
// and expressions can be used to indicate if a parameter
// is non-nullable or an array.

/**
 * Greets a user
 * @param {string} name - The user's name
 */
function sayHello(name) {
  alert('Hello ' + name);
}
# JSDoc cheatsheet

Tag @param

// The @returns tag is used to describe
// the value that a function returns.
// 
// The syntax is:
// @returns {Type} Description.

/**
 * Adds two numbers
 * @param {number} a - The first number
 * @param {number} b - The second number
 * @returns {number} The sum of numbers a and b
 */
function add(a, b) {
  return a + b;
}
# JSDoc cheatsheet

Tag @returns

/**
 * Divides two numbers
 * @param {number} a - The numerator
 * @param {number} b - The denominator, must not be 0
 * @throws {Error} If the denominator is 0,
 * an error is thrown indicating division by zero
 * is not allowed.
 * @returns {number} The result of the division a / b
 */
function divide(a, b) {
  if (b === 0) {
    throw new Error('Division by zero is not allowed.');
  }
  return a / b;
}
# JSDoc cheatsheet

Tag @throws

/**
 * Fetches data from a URL asynchronously
 * @async
 * @param {string} url - The URL to fetch data from
 * @returns {Promise<Object>} A promise resolving to
 * the data fetched from the URL
 */
async function fetchData(url) {
  const response = await fetch(url);
  return response.json();
}
# JSDoc cheatsheet

Tag @async

/**
 * Possible title for this talk
 * @type {string} 
 * @author Exiliot [exiliot@example.com]
 */
const talkTitle =  "Demystifying JSDoc"
# JSDoc cheatsheet

Tag @author

/** 
 * Sums of the square of two numbers a**2 + b**2
 * @example <caption>How to use the sumSquares function</caption>
 * // returns 13 
 * sumSquares(2, 3)
 * @example
 * // returns 41
 * sumSquares(4, 5)
 * // Typing the function
 * @param {number} a - The first number
 * @param {number} b - The second number
 * @returns {Number} Returns the sum of the squares
 * */
const sumSquares = function(a, b){
    return a**2 + b**2
}
# JSDoc cheatsheet

Tag @example

/** 
 * @version 1.0.0
 * @type {number} 
 **/
const meaningOfLife = 42
# JSDoc cheatsheet

Tag @version

/** 
 * How to use the link tags
 * Also see the {@link https://jsdoc.app/tags-inline-link.html official docs} for more information
 * @tutorial getting-started
 **/
function myFunction (){
}
# JSDoc cheatsheet

Tag @link

Work with React

/**
 * Represents a greeting component that displays a welcome message.
 * 
 * @component
 * @param {Object} props - The properties passed to the component.
 * @param {string} props.name - The name of the person to greet.
 * @returns {JSX.Element} A greeting message wrapped in a <div>.
 */
const Greeting = ({ name }) => <div>Hello, {name}!</div>;
# JSDoc cheatsheet

Functional component

import React from 'react';

/**
 * @typedef Props
 * @prop {React.ReactNode} title
 * @prop {React.ReactNode} [desc]
 * @prop {React.ReactNode} [selectFlightPrompt]
 * @prop {()=>void} [onLogin]
 */

/**
 * @param {Props} props
 */
const InflowHeader = ({ title, desc, selectFlightPrompt, onLogin }) => (
 ...
);
# JSDoc cheatsheet

Functional component

/**
 * @typedef Props
 * @prop {any} resource
 */

/**
 * @typedef State
 * @prop {boolean} isDrawerOpen
 */
# JSDoc cheatsheet

Class component

/**
 * @extends Component<Props, State>
 */
class SampleContainer extends Component {
    /** @type {State} */
    state = {
        isDrawerOpen: false,
    };

    constructor(props){
        super(props);
    }

    render() {
        return <>...</>;
    }
}
# JSDoc cheatsheet

Class component

/**
 * Custom hook for managing and toggling boolean state.
 *
 * @returns {[boolean, () => void]} Current state and
 * a function to toggle the state.
 *
 * @example
 * const [isOpen, toggleOpen] = useToggle(false);
 */
const useToggle = (initialState = false) => {
  const [state, setState] = useState(initialState);

  const toggle = () => setState(!state);

  return [state, toggle];
};
# JSDoc cheatsheet

Hook

/**
 * Custom hook for managing and toggling boolean state.
 *
 * @typedef {Object} HookResult - The result of the hook.
 * @property {boolean} state - The current boolean state.
 * @property {Function} toggle - Function to toggle the
 * state.
 *
 * @param {boolean} [initialState=false] - The initial state.
 * @returns {HookResult} Current state and a function to
 * toggle the state.
 */
const useToggle = (initialState = false) => {
  const [state, setState] = useState(initialState);
  const toggle = () => setState(!state);
  return [state, toggle];
};
# JSDoc cheatsheet

Hook

JSDoc + IntelliSense = ♥️

# JSDOC + IntelliSense

Typehinting in VSCode with JSDoc help

# JSDOC + IntelliSense

Using @typedef to define custom type definitions 

JSDoc vs TypeScript

JSDoc and TypeScript both solve the problems with writing and maintaining plain JavaScript code.

However, they used different approaches, which have their benefits and drawbacks.

Benefits of JSDoc over TypeScript

Flexibility & Compatability

JSDoc being just JS comments, means it could be added to any JS codebase regardless of the language version, and it is not tied to a compiler like TypeScript is.

1.

2.

Code Annotation

JSDoc could be used for more than just type checking. It could be used to add more documentation, describe how functions work, and generate a documentationwebsite, all providing value to enhance code maintainability and understanding.

3.

No Compilation Step

TypeScript requires compilation to change the TypeScript code into JS so the engine can understand it, while JSDoc does not require any other step as they are just "comments", which is supported feature of JS itself.

# CHAPTER 2

Drawbacks of using JSDoc

Stronger Static Typing

TypeScript provides a strong model for types and catches these errors at compile time. Unlike JSDoc, where these typing end in the code itself and isn't enforced.

1.

2.

Type Inference

TypeScript can infer the type from its value. This helps reduce explicit type annotations and makes the codebase less verbose.

3.

Transpilation

TypeScript can adopt the latest and future features of the JS language with its polyfill feature. It effectively transpiles these codes down to understandable versions for browsers that would not have support for the features yet.

# CHAPTER 2
// TypeScript
function stringsStringStrings(p1: string, p2?: string, p3?: string, p4 = "test"): string {
  // ...
}

// JSDoc
/**
 * @param {string}  p1
 * @param {string=} p2
 * @param {string} [p3]
 * @param {string} [p4="test"]
 * @return {string}
 */
function stringsStringStrings(p1, p2, p3, p4) {
  // ...
}
# PRESENTING CODE

Readability

const thing = document.querySelector('#my-element')
addStuff(thing); // Error: type undefined is not assignable to type Thing 
// or
const data = await fetch('https://my-url.dev');
return data.results // error: data is possibly undefined

// TypeScript
const thing = document.querySelector('#my-element')
addStuff(thing!); // although probably don't do this 
addStuff(thing as Thing) // still not great but it works

// JSDoc
const thing = document.querySelector('#my-element')
addStuff(
// thing is definitely defined by this point, see line 120
// @ts-ignore-next-line
  thing
);
# PRESENTING CODE

Flexibility

  • Complementary Documentation
  • Richer IDE Support
  • Usage Examples
  • Descriptive Annotations

JSDoc in TypeScript:
Enhancing Documentation

Improving DX with Better Tooling

# PRESENTING CODE
# PRESENTING CODE
  • Highlight lines containing diagnostics
  • Append diagnostic as text to the end of the line
  • Show icons in gutter
  • Show message in status bar
# PRESENTING CODE

The End :)

From JSDoc to TypeScript

By Nikita Malik

From JSDoc to TypeScript

  • 54