Skip to content

Instantly share code, notes, and snippets.

  • Star 12 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save hrdtbs/f7e567c0738725a16a9de7326dc11127 to your computer and use it in GitHub Desktop.

JSDocで型安全にJavaScriptを扱う

TypeScript や Flow ではなく JSDoc を用いた JavaScript のプロジェクトは多くありますが、特別なことをしない限り、 悲しいことに JSDoc を書いても、何も言ってくれません。

/** @type {Array} foo */
let foo = [];

foo = "foo"; // 何も言ってくれない...
console.log(foo); // foo

Visual Studio Code に置ける特別なことの選択肢の一つとして、TypeScript エンジンにチェックしてもらう方法があります。 ファイルの一番上に// @ts-checkを加えてみましょう。エラーを吐いてくれます。

// @ts-check
/** @type {Array} foo */
let foo = [];

foo = "foo"; // Error:型 '0' を型 'string' に割り当てることはできません。
console.log(foo);

また、それ以外の環境でも次のようにして確認することができます。

$ tsc --allowJs --checkJs --noEmit --target ES5 src/*.js

記述例

/**
 * @type {string}
 */
const foo = "foo";
/** @type {string} */
/** @type {string|number} */
/** @type {string|number|undefined} */
/** @type {any} */

Function

/** @type {Function} */
/**
 * Set the title with the provided value.
 * @param {string} newTitle
 * @return {Node} H1 element.
 */
function setTitle(newTitle) {
  return <h1>{newTitle}</h1>;
}

Array

/** @type {Array<string>} */
/** @type {Array<string>} */
/** @type {string[]} */
const foo = ["foo", "bar"];

/** @type {Array<string|number>} */
const foo = ["foo", "bar", 0, 1];

/** @type {Array[]} */
const foo = [[], []];

Object

/** @type {Object<string, string|number>} */
/** @type {Object.<string, string|number>} */
/** @type {{string, string|number}} */
/** @type {Object.<string, string|number>} */
const foo = { foo: "foo", bar: 2 };

/** @type {Object<string, Object<number, string>} */
const foo = { foo: { 1: "foo", 2: "foo" }, bar: { 3: "bar" } };

Object's propperty

/** @type {{foo:string, bar:number}} */
const props = {
  foo: "foo",
  bar: 1
};

/**
 * @typedef {Object<string, number>} Props
 * @property {string} foo
 * @property {number} bar
 */
/**
 * @type {Props}
 */

Map, Set, ...

/** @type Map.<string, any> */
/** @type Map<string, any> */

/** @type Set.<string> */
/** @type Set<string> */

ES6 Class

/**
 * Class to create a person object.
 */
class Person {
  constructor(props) {
    /**
     * @property {string} name The person's name.
     */
    this.name = props.name;
    /**
     * @property {number} age The person's name.
     */
    this.age = props.age;
    /**
     * @property {Function} sayName A method to annouce the person's name.
     * @returns void
     */
    this.sayName = () => alert(this.name);
  }
}

Import

ライブラリの型定義を使いたい場合

/** @type {Map.<string, import("eslint").Rule.RuleModule>} */
const rules = engine.getRules();

自分で定義した d.ts ファイルを使いたい場合

foo.d.ts

export interface Foo {
  foo: string;
  bar: string | {} | number;
}
/** @type {import("../foo").Foo} */

自分で定義した JSDoc の記述を使いたい場合

foo.js

/**
 * @typedef {string, string | {} | number} Foo
 * @property {string} foo
 * @property {string} bar
 */
/** @type {import("../foo").Foo} */

Optional Parameters

/** @type {{foo:string, bar:number, bar2?:number}} */
const props = {
  foo: "foo",
  bar: 1
};
/**
 * @typedef {Object<string, number>} Props
 * @property {string} foo
 * @property {number} bar
 * @property {number} [bar2]
 */
/**
 * @type {Props}
 */

Generics

// Generic types may also be used
/**
 * @template T
 * @param {T} param - A generic parameter that flows through to the return type
 * @return {T}
 */
function genericFnc(param) {
  return param;
}

Type Casting

const btn = document.createElement("button");
/** @type {Element} */ (btn).setAttribute("disabled", "true");
@hrdtbs
Copy link
Author

hrdtbs commented Mar 5, 2019

VSCodeで@ propertyで書いた型の認識がおかしい場合があります。

@hrdtbs
Copy link
Author

hrdtbs commented Mar 5, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment