การตรวจสอบประเภทใน 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 จากบรรทัดคำสั่ง ได้ ฉันต้องการ:
- ไฟล์ TS ทั้งหมด ที่ระบุไว้ตอนเริ่มต้นจะถูกตรวจสอบประเภท;
- เฉพาะ ไฟล์ TS ที่ระบุไว้ตอนเริ่มต้นเท่านั้นที่จะถูกตรวจสอบประเภท;
- การแยกการตรวจสอบประเภทระหว่างโปรเจกต์ให้คงอยู่ (เช่น เมื่อกำลังตรวจสอบไฟล์ซอร์สที่อยู่ในโปรเจกต์
fooจะต้องรวมเฉพาะแพ็กเกจ@typeและคำจำกัดความประเภทของแพ็กเกจที่ระบุในpackages/foo/package.jsonและติดตั้งอยู่ภายใต้packages/foo/node_modulesเท่านั้น); - ไฟล์เดียวกันจะไม่ได้รับการตรวจสอบชนิดหลายครั้ง (เพื่อประหยัดเวลาและเพื่อไม่ให้ข้อผิดพลาดเกี่ยวกับชนิดซ้ำรายงานสองครั้ง)
tsc --project tsconfig.json
- ผ่าน: ราก
tsconfigรวมไฟล์.tsทั้งหมดในรีโปยกเว้นไฟล์ที่อยู่ใต้node_modules - ล้มเหลว: ไฟล์
.tsที่อยู่ภายในโฟลเดอร์เอาต์พุต (dist,build,outเป็นต้น) ก็ถูกตรวจสอบประเภทด้วยเช่นกัน - ล้มเหลว: แพ็กเกจ
@typeทั้งหมดและการกำหนดชนิดจะถูกรวมเข้าไป ซึ่งทำให้การแยกกันระหว่างโปรเจกต์เสีย และก่อให้เกิดความขัดแย้งสำหรับชนิดทั่วโลก (เช่น Cypress กับ Jest) ทำให้การตรวจสอบชนิดไม่เชื่อถือได้ - ผ่าน:
tscรันเพียงครั้งเดียว ดังนั้นจึงไม่มีปัญหาใด ๆ ที่นี่
tsc --project tsconfig.check.json
ด้วย tsconfig.check.json:
{
"extends": "./tsconfig.json",
"include": ["*.ts", "packages/*/*.ts, "packages/*/src/**/*.ts", ...]
}
- ผ่าน
- PASS: น่ารำคาญและง่ายต่อการลืมที่จะรักษาความสอดคล้อง แต่ใช้งานได้
- ล้มเหลว: ยังคงไม่มีการแยกตัว
- ผ่าน
tsc -p tsconfig.check.json && tsc -p packages/foo/tsconfig.json && ...
โดยมีราก tsconfig.check.json รวม ["*.ts"] และ tsconfig.json ของโปรเจกต์ถูกแก้ไขเพื่อรวม ["*.ts", "src/**/*.ts"]
คำสั่ง
tscของแต่ละโปรเจกต์สามารถใส่ในสคริปต์ NPM เพื่อใช้ประโยชน์จากความสามารถของ pnpm ในการรันสคริปต์แบบเรียกซ้ำได้
- ผ่าน
- ผ่าน: โฟลเดอร์เอาต์พุตไม่ได้ถูกรวมอยู่ด้วย.
- ผ่าน:
tsconfig.check.jsonไม่รวมไฟล์โครงการ และtsconfig.jsonของโครงการเหล่านั้นเป็นเอกเทศต่อกัน (เช่น พวกมันไม่รวมไฟล์ของกันและกัน) - ล้มเหลว: หากโปรเจกต์
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 แบบใดแบบหนึ่ง?
- ...?