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

การตรวจสอบประเภทใน monorepo ของ TypeScript


บริบท

ฉันทำงานบน monorepo ของ TypeScript ที่ตั้งค่าด้วย pnpm ไฟล์ TypeScript อยู่ในหลายที่:

  • ไฟล์ต้นฉบับของโครงการ (packages/*/src/**/*.ts);
  • ไฟล์คอนฟิกที่รากของรีโป (*.ts);
  • ไฟล์คอนฟิกที่รูทของโฟลเดอร์โครงการ (packages/*/*.ts);
  • สเปคของ Cypress และไฟล์คอนฟิกของ Cypress (cypress/**/*.ts)

เมื่อฉันเปิดไฟล์ใดไฟล์หนึ่งเหล่านั้นใน VS Code ฉันต้องการให้เซิร์ฟเวอร์ภาษา TypeScript ตรวจสอบประเภทของไฟล์ เพื่อที่ VS Code จะสามารถขีดเส้นใต้ปัญหาในตัวแก้ไขได้

เพื่อให้บรรลุเป้าหมายนี้ ฉันมีไฟล์ tsconfig.json รากที่กำหนดการตรวจสอบประเภทอย่างเข้มงวดสำหรับไฟล์ TS ทั้งหมดในมอนอรีโป (แน่นอนว่าไม่รวม node_modules) มันมีลักษณะดังนี้:

{
  "compilerOptions": {
     "strict": true,
     "noEmit": true,
     ... // lot more options
  }
}

เพื่อให้ VS Code ตรวจสอบประเภทของไฟล์ซอร์สในโฟลเดอร์โปรเจกต์ได้อย่างถูกต้อง โดยเฉพาะการทำให้แน่ใจว่า มีการโหลดแพ็กเกจ @types ที่เกี่ยวข้องกับแต่ละโปรเจกต์เท่านั้น ผมจึงวางไฟล์ tsconfig.json ไว้ในแต่ละโฟลเดอร์โปรเจกต์โดยที่ไฟล์นี้สืบทอดจาก tsconfig.json ของรากโฟลเดอร์ monorepo:

{
  "extends": "../../tsconfig.json"
}

ไฟล์ tsconfig.json ในโฟลเดอร์ cypress มีบางอย่างเพิ่มเติมอยู่บ้าง แต่แนวคิดโดยรวมก็เหมือนกัน

ปัญหา

ในตอนนี้ monorepo ได้ถูกตั้งค่าให้ตรวจสอบประเภทใน VS Code ฉันสามารถเปิดไฟล์ .ts ใดก็ได้ และเซิร์ฟเวอร์ภาษาจะแจ้งปัญหาเรื่องประเภทได้อย่างถูกต้อง

ตอนนี้ฉันจำเป็นต้องสามารถ ตรวจสอบชนิดข้อมูลของทั้ง monorepo จากบรรทัดคำสั่ง ได้ ฉันต้องการ:

  1. ไฟล์ TS ทั้งหมด ที่ระบุไว้ตอนเริ่มต้นจะถูกตรวจสอบประเภท;
  2. เฉพาะ ไฟล์ TS ที่ระบุไว้ตอนเริ่มต้นเท่านั้นที่จะถูกตรวจสอบประเภท;
  3. การแยกการตรวจสอบประเภทระหว่างโปรเจกต์ให้คงอยู่ (เช่น เมื่อกำลังตรวจสอบไฟล์ซอร์สที่อยู่ในโปรเจกต์ foo จะต้องรวมเฉพาะแพ็กเกจ @type และคำจำกัดความประเภทของแพ็กเกจที่ระบุใน packages/foo/package.json และติดตั้งอยู่ภายใต้ packages/foo/node_modules เท่านั้น);
  4. ไฟล์เดียวกันจะไม่ได้รับการตรวจสอบชนิดหลายครั้ง (เพื่อประหยัดเวลาและเพื่อไม่ให้ข้อผิดพลาดเกี่ยวกับชนิดซ้ำรายงานสองครั้ง)

tsc --project tsconfig.json

  1. ผ่าน: ราก tsconfig รวมไฟล์ .ts ทั้งหมดในรีโปยกเว้นไฟล์ที่อยู่ใต้ node_modules
  2. ล้มเหลว: ไฟล์ .ts ที่อยู่ภายในโฟลเดอร์เอาต์พุต (dist, build, out เป็นต้น) ก็ถูกตรวจสอบประเภทด้วยเช่นกัน
  3. ล้มเหลว: แพ็กเกจ @type ทั้งหมดและการกำหนดชนิดจะถูกรวมเข้าไป ซึ่งทำให้การแยกกันระหว่างโปรเจกต์เสีย และก่อให้เกิดความขัดแย้งสำหรับชนิดทั่วโลก (เช่น Cypress กับ Jest) ทำให้การตรวจสอบชนิดไม่เชื่อถือได้
  4. ผ่าน: tsc รันเพียงครั้งเดียว ดังนั้นจึงไม่มีปัญหาใด ๆ ที่นี่

tsc --project tsconfig.check.json

ด้วย tsconfig.check.json:

{
  "extends": "./tsconfig.json",
  "include": ["*.ts", "packages/*/*.ts, "packages/*/src/**/*.ts", ...]
}
  1. ผ่าน
  2. PASS: น่ารำคาญและง่ายต่อการลืมที่จะรักษาความสอดคล้อง แต่ใช้งานได้
  3. ล้มเหลว: ยังคงไม่มีการแยกตัว
  4. ผ่าน

tsc -p tsconfig.check.json && tsc -p packages/foo/tsconfig.json && ...

โดยมีราก tsconfig.check.json รวม ["*.ts"] และ tsconfig.json ของโปรเจกต์ถูกแก้ไขเพื่อรวม ["*.ts", "src/**/*.ts"]

คำสั่ง tsc ของแต่ละโปรเจกต์สามารถใส่ในสคริปต์ NPM เพื่อใช้ประโยชน์จากความสามารถของ pnpm ในการรันสคริปต์แบบเรียกซ้ำได้

  1. ผ่าน
  2. ผ่าน: โฟลเดอร์เอาต์พุตไม่ได้ถูกรวมอยู่ด้วย.
  3. ผ่าน: tsconfig.check.json ไม่รวมไฟล์โครงการ และ tsconfig.json ของโครงการเหล่านั้นเป็นเอกเทศต่อกัน (เช่น พวกมันไม่รวมไฟล์ของกันและกัน)
  4. ล้มเหลว: หากโปรเจกต์ foo นำเข้าไฟล์จากโปรเจกต์ bar และ tsc รันทั้งสำหรับ foo และ bar ไฟล์ที่นำเข้าจะถูกตรวจสอบประเภทซ้ำสองครั้ง; และถ้า tsc รันเฉพาะบน foo และไม่รันบน bar ไฟล์ใน bar ที่ ไม่ ถูกนำโดย foo จะไม่ได้รับการตรวจสอบประเภท (เช่น ไฟล์ทดสอบ)

การอ้างอิงโครงการ TypeScript

ถ้าฉันไม่เข้าใจผิด, tsc --build --noEmit ยังไม่รองรับ

สิ่งที่ฉันกำลังตามหา...

  • วิธีการรัน tsc หนึ่งครั้งจากรากของ monorepo ในขณะที่ยังคำนึงถึงไฟล์ tsconfig.json ที่ซ้อนอยู่ได้เหมือนกับ language server ของ VS Code?
  • เครื่องมือที่สามารถตรวจสอบประเภทได้เหมือน tsc แต่ไม่มีข้อจำกัดที่ฉันกำลังอธิบายอยู่?
  • วิธีการจัดโครงสร้างไฟล์ tsconfig ของฉันเพื่อให้ผ่านทั้งสี่ข้อกำหนดข้างต้น และโดยไม่สูญเสียการตรวจสอบชนิดข้อมูลใน IDE?
  • สคริปต์ที่ใช้ประโยชน์จาก TypeScript Compiler API แบบใดแบบหนึ่ง?
  • ...?

บทความที่เกี่ยวข้อง