ค้นหาเว็บไซต์

วิธีพิมพ์ฟังก์ชัน JavaScript ด้วย JSDoc + TypeScript?


อัปเดต (2023)

ฉันจริงๆ แล้วได้พูดในการบรรยายเกี่ยวกับวิธีการใช้ tsc + JSDoc ที่ตอบคำถามนี้และอีกหลายคำถาม:

  • https://jswithtypes.com

และสร้างแพ็กเกจเพื่อช่วยกับโค้ดพื้นฐานของ tsconfig:

  • https://npmjs.org/jswt

    npx jswt init
    

คำถามต้นฉบับ

ฉันกำลังพยายามใช้ tsc กับ JavaScript ธรรมดาและฉันงงว่าต้องประกาศชนิดของฟังก์ชันอย่างไร

ดูเหมือนว่ามันควรง่ายเพียงแค่นี้:

/** @type PersonGreet */
person.greet = function greet(other) {
  return `Hello ${other.name}, my name is ${person.name}!`;
};

แก้ไข: /** @type PersonGreet */ ถูกต้อง พฤติกรรมปัจจุบันเป็นข้อบกพร่องใน tsc คำตอบที่เลือกด้านล่างให้วิธีแก้ไขที่ถูกต้อง

กรณีทดสอบที่ลดลง

ละเว้นความจริงที่ว่าอาจมีใครบางคนต้องการปรับโครงสร้างใหม่นี้โดยใช้คลาสหรือโพรโทไทป์หรืออะไรทำนองนั้น - มันก็ทำหน้าที่ได้ดีในฐานะตัวอย่างของปัญหา

รีโพ: https://github.com/BeyondCodeBootcamp/hello-tsc

"use strict";

/**
 * @typedef {Object} Person
 * @property {String} name
 * @property {PersonGreet} greet
 */

/**
 * @typedef {Function} PersonGreet
 * @param {Person} other
 * @returns {String}
 */

let Person = {};

/**
 * Creates a person
 * @param {Object} p
 * @param {String} p.name
 * @returns {Person}
 */
Person.create = function (p) {
  let person = {};

  person.name = p.name;

  /////////////////////////////////////////////////////////////////////////////////
  //
  // error TS7006: Parameter 'other' implicitly has an 'any' type.  <======= WRONG!
  //
  /////////////////////////////////////////////////////////////////////////////////

  /** @type PersonGreet */
  person.greet = function greet(other) {
    return `Hello ${other.name}, my name is ${person.name}!`;
  };

  return person;
};

module.exports = Person;

พิมพ์ผิดเป็น 'any'

เมื่อฉันรัน tsc เพื่อเช็ค มันจะแสดงข้อผิดพลาดเกี่ยวกับ implicit any:

tsc -p jsconfig.json
person.js:28:33 - error TS7006: Parameter 'other' implicitly has an 'any' type.

28   person.greet = function greet(other) {
                                   ~~~~~


Found 1 error in person.js:28

ทำอย่างไรดี?

สำหรับฉัน สิ่งนี้ดูเหมือนเป็นบั๊กใน tsc... แต่สิ่งนี้เป็นเรื่องพื้นฐานของ JS 101 แน่นอนว่าต้องมีวิธีในการกำหนดประเภทให้ฟังก์ชันใช่ไหม?

ฉันต้องใช้คำอธิบายประกอบอะไรในการประกาศประเภทของฟังก์ชัน? หรือว่า tsc/tsserver/typescript ไม่สามารถจัดการกับการใช้งานพื้นฐานแบบนี้ของ JS ได้เลย?

คำตอบ #1

วิธีแก้ปัญหา 1

คุณควรใช้ @callback แทน @function ดังนี้:

"use strict";

/**
 * @typedef {Object} Person
 * @property {String} name
 * @property {PersonGreet} greet
 */

/**
 * @callback PersonGreet
 * @param {Person} other
 * @returns {String}
 */

let Person = {};

/**
 * Creates a person
 * @param {Object} p
 * @param {String} p.name
 * @returns {Person}
 */
Person.create = function (p) {
  let person = {};

  person.name = p.name;

  /** @type {PersonGreet} */
  person.greet = function greet(other) {
    return `Hello ${other.name}, my name is ${person.name}!`;
  };

  return person;
};

module.exports = Person;

วิธีแก้ปัญหา 2

หรือ ประกาศ @typedef โดยใช้ไวยากรณ์ของ TypeScript ดังต่อไปนี้:

/**
 * @typedef {(other: Person) => string} PersonGreet
 */