添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

由於 Javascript 是動態型別語言,變數型別的寬容使得程式撰寫上有不錯的靈活性,但是當專案變得龐大時,反而會使開發成本提高。

使用 TypeScript 能有效解決動態型別的缺點,但考慮到學習成本與舊專案的重構,可試試 VSCode 中基於 TypeScript 提供對於 JSDoc 支持,實現智能型別檢查。

1. 開啟型別檢查

最簡單的方法就是在 .js 檔案開頭新增 @ts-check

// @ts-check

那麼 VSCode 就會根據註解檢查型別。

如果不想每隻 .js 檔案都加上 @ts-check,可以開啟 VSCode 全域型別檢查:

"js/ts.implicitProjectConfig.checkJs": true

預設的情況下是關閉的:

如果型別檢查為開啟,則可以使用 @ts-nocheck 忽略某隻檔案的類型檢查:

// @ts-nocheck

2. jsconfig.json

除了啟用 VSCode 的設定來開啟型別檢查,也可以在專案根目錄下新增 jsconfig.json 設定檔:

"compilerOptions": { "checkJs": true

jsconfig.json 會覆蓋 Implicit Project Config: Check JS 設定。

預設會全域檢查所有 .js 檔案,可以使用 excludeinclude 選項,設定要排除或包含的資料夾:

"compilerOptions": { "checkJs": true "exclude": ["node_modules", "dist"], "include": ["src/**/*"]

Visual Studio Code - jsconfig.json
TypeScript - What is a tsconfig.json

3. 支持的 JSDoc 標籤

TypeScript 只支持了部分 JSDoc 標籤。

當前所支持的標籤如下:

  • @type
  • @param (or @arg or @argument)
  • @returns (or @return)
  • @typedef
  • @callback
  • @template
  • @class (or @constructor)
  • @this
  • @extends (or @augments)
  • @enum
  • JSDoc Reference

    3. 簡單範例

    JSDoc 註解格式必須以 /** 為開頭才能被識別(例如 /*/*** 不會被解析為 JSDoc 註解):

    /** */
    

    舉例來說,我們定義一個 count 變數:

    let count;
    

    我們可以指定任何型別的值給它,但如果希望它只接受數字型別,可以加上 JSDoc 註解:

    /** @type {number} */
    let count;
    

    若指定非數字型別的值,VSCode 將會跳出錯誤提示:

    可以在註解第一行加上說明:

    * 計數變數 * @type {number} let count;

    如果想要忽略類型錯誤可以使用 @ts-ignore

    JSDoc 標籤

    1. @type

    @type 可以用來標明變數型別。

    基本用法:

    /** @type {string} */
    let str;
    str = 'Hello!';
    /** @type {Date} */
    let now;
    now = new Date();
    /** @type {HTMLElement} */
    let dom;
    dom = document.querySelector('body');
    

    複合型別:

    /** @type {string|boolean} */
    let x;
    x = '123';
    x = true;
    

    指定陣列元素的型別:

    /** @type {number[]} */
    const ns = [];
    [].push(1);
    

    也可以寫成 Array.<number>Array<number>

    /** @type {Array.<number>} */
    const ns = [];
    /** @type {Array<number>} */
    const ns2 = [];
    

    物件字面值:

    * @type {{ a: string, b: number }} let obj; obj = { a: '123', b: 123 };

    指定 map-likearray-like 的物件:

    * @type {Object.<string, number>} let stringToNumber; /** @type {Object.<number, object>} */ let arrayLike;

    預設就是 any 任意型別:

    /** @type {any} */
    let x;
    

    *? 等同 any

    /** @type {*} - can be 'any' type*/
    let y;
    /** @type {?} - unknown type*/
    let z;
    

    函式型別:

    * @type {function(number): number} Closure syntax let foo; foo = function (a) { return a * a; * @type {(a: number) => number} Typescript syntax let boo; boo = function (a) { return a * a;

    2. @param(synonyms: @arg or @argument)

    @param 語法和 @type 基本上相同,但用於標明函式參數,所以多了參數名稱。

    * The square of a number * @param {number} number - 輸入數字 * @return {number} function square(number) { return number * number;

    函式如果有回傳值,則可以使用 @returns@return) 標明。

    有屬性的參數,使用物件字面值不易描述屬性:

    * @param {{ name: string, age: number }} person function foo(person) { console.log(person.name, person.age);

    可以使用以下寫法:

    * @param {Object} person - 某人 * @param {string} person.name - 某人的名字 * @param {number} person.age - 某人的年齡 function foo(person) { console.log(person.name, person.age);

    使用 ES6 參數解構,使用適當的參數名稱即可:

    * @param {Object} person - 某人 * @param {string} person.name - 名字 * @param {number} person.age - 年齡 function foo({ name, age }) { console.log(name, age);

    可選參數表示方式:

    * @param {string=} p1 - 可選參數(Closure語法) * @param {string} [p2] - 可選參數(JSDoc語法) * @param {string} [p3 = 'test'] - 有預設值的可選參數(JSDoc語法) function foo(p1, p2, p3 = 'test') {}

    3. @typedef

    @typedef 可以用來宣告複雜型別,也就是自訂義一個類型,再使用 @type 標記來引用。

    描述一個物件型別:

    * @typedef {Object} SpecialType - creates a new type named 'SpecialType' * @property {string} prop1 - a string property * @property {number} prop2 - a number property * @prop {number} [prop3] - an optional number property of SpecialType /** @type {SpecialType} */ let obj; obj = { prop1: '123', prop2: 123 };

    4. @callback

    @callback@typedef 相似,但描述的是一個函式:

    * @callback Predicate * @param {string} data * @returns {boolean} /** @type {Predicate} */ const foo = function (str) { return !(str.length % 2);

    5. @class(synonyms: @constructor)

    @class 可以標明函式為一個建構函式(Constructor)

    * Creates a new Person. * @class function Person() {} const p = new Person();

    不過 ES6 有了 class 後,就沒必要使用 @class 了。

    class Person {
       * Creates a new Person.
      constructor() {}
    

    6. @this

    @this 可以明確標示 this 關鍵字在這裡指的是什麼。

    例如建構函式的方法:

    * @class function Person() { this.name = ''; * @this {Person} - Person 實體 Person.prototype.setName = function (name) { this.name = name;

    或監聽器處理函式:

    * @param {Event} event - 事件物件 * @this {HTMLElement} - 監聽器綁定元素 function clickHandler(event) { // ...

    7. @extends(synonyms: @augments)

    如果使用 extends 關鍵字來擴展一個現有的類別的時候,可以使用 @extends 標示。

    /** 佇列 */
    class Queue {}
     * 優先佇列
     * @extends Queue
    class PriorityQueue extends Queue {}
    

    8. @enum

    @enum 標籤描述一個靜態屬性值的全部相同的集合,簡單來說就是一個物件內的屬性皆為相同型別,且不允許新增額外屬性。

    /** @enum {number} */
    const JSDocState = {
      BeginningOfLine: 0,
      SawAsterisk: 1,
      SavingComments: 2,
    

    9. @template

    @templete 非 JSDoc 標準,只在 google closure compiler 中有提及,可以用來宣告 泛用型別(Generic Type),是 TypeScript 中的型別。

    泛用型別(Generic Type) 目的在於成員之間提供有意義的約束,這些成員可以是類別的實體、類別的方法、函式參數、函式回傳值。

    * @template T * @param {T} x * @return {T} function foo(x) { return x;

    關於 泛用型別(Generic Type) 我自己也不是很了解,有空在補充。

    註解相關 VSCode 套件

  • koroFileHeader,在 VSCode 中用於生成檔案頭部註解和函式註解的套件。
  • 文件頭部新增註解:Ctrl + Alt + t
  • 光標處添加函式註解:Ctrl + Alt + t
  • Todo Tree,特殊註解高光亮。
  • // 配置
    "todo-tree.general.tags": ["TODO:", "FIXME:"],
    "todo-tree.highlights.defaultHighlight": {
      "gutterIcon": true,
      "foreground": "#fff",
      "type": "text",
      "opacity": 50
    "todo-tree.highlights.customHighlight": {
      "TODO:": {
        "background": "#ffbd2a",
        "iconColour": "#ffbd2a"
      "FIXME:": {
        "background": "#f06292",
        "iconColour": "#f06292",
        "icon": "flame"
    
  • 可不可以不要寫糙 code系列 第 8 篇 - 不必要的註解
  • 编写高质量可维护的代码:一目了然的注释
  • 導入 TypeScript 應考慮之效益與成本
  • 為你的 JavaScript 項目添加智能提示和類型檢查
  • [Vuex]在 Vscode 中不使用 Typescript 也能讓 Vuex 讀懂變數的類型
  • JSDoc中文文档(@use JSDoc)
  • 基于TypeScript的JSDoc注释
  • @ts-check 立即上手,JSDoc 添加类型
  • 如何使用 JSDoc 保證你的 Javascript 型別安全性
  • TS in JS 实践指北
  • [Web翻译]从JavaScript生成TypeScript定义文件
  • [译] 讨论 JS ⚡:文档
  • 使用 JSDoc 标注类型
  • 利用 VSCode、JSDoc、d.ts 让你的代码更健壮
  • ES6写JSDoc的一些经验和实例
  • 震驚!JavaScript 竟然可以類型推斷!
  • “無 Typescript” 編程
  • JSDoc support in JavaScript
  • JSDoc支持_TypeScript筆記19
  • Typescript 初心者手札系列 第 3 篇 - TypeScript 編譯設定 - tsconfig.json
  • vscode中的 jsconfig.json
  • 為什麼世界需要Typescript系列 第 7 篇 - 泛型 - 07
  • 你不知道的 TypeScript 泛型(萬字長文,建議收藏)
  • TypeScript系列(四)泛型
  •