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

jquery - ติดตั้งการกำหนดประเภท TypeScript หลายตัวที่ประกาศตัวแปร global เดียวกัน


ฉันกำลังสร้างแอปพลิเคชันโดยใช้ TypeScript, Node และ Electron

ฉันกำลังใช้ jQuery ในแอปพลิเคชันและฉันได้ติดตั้งแพ็กเกจ @types/jquery เพื่อให้มีคำแนะนำ Intellisense

ต่อไปฉันสร้างการทดสอบโดยใช้ mocha และ spectron Spectron ใช้ประโยชน์จาก webdriverio และเปิดเผย API ของมันผ่านคุณสมบัติบางอย่าง ฉันจำเป็นต้องใช้คุณสมบัติเหล่านี้ ดังนั้นฉันจึงติดตั้ง @types/webdriverio เพื่อให้ได้รับคำแนะนำ intellisense

ตอนนี้ ทุกครั้งที่ฉันรันเครื่องมือ tsc เพื่อคอมไพล์โปรเจกต์ ฉันจะได้รับข้อผิดพลาดดังต่อไปนี้:

node_modules/@types/jquery/index.d.ts(36,15): error TS2451: Cannot redeclare block-scoped variable '$'.
node_modules/@types/webdriverio/index.d.ts(1898,18): error TS2451: Cannot redeclare block-scoped variable '$'.
node_modules/@types/webdriverio/index.d.ts(1899,18): error TS2451: Cannot redeclare block-scoped variable '$'.

ปัญหาคือทั้งสองแพ็กเกจประกาศตัวแปร $ แบบ global คุณสามารถตรวจสอบได้ในหน้าของพวกเขาบน npm ภายใต้ "Global values" ด้วยเช่นกัน:

https://www.npmjs.com/package/@types/jquery

https://www.npmjs.com/package/@types/webdriverio

สิ่งที่ฉันไม่เข้าใจก็คือทำไม tsc ถึงพยายามคอมไพล์พวกมันด้วยกันทั้งที่ฉันไม่ได้ใช้ jquery และ webdriverio ในไฟล์ .ts เดียวกัน?

นอกจากนี้ แม้ว่าฉันจะคอมเมนต์โค้ดทดสอบออก ซึ่งทำให้ฉันไม่อ้างอิง webdriverio ที่ไหนเลย แต่เมื่อฉันรัน tsc ฉันก็ยังได้รับข้อผิดพลาดเหมือนเดิม อาจเป็นเพราะ tsc กำลังคอมไพล์ซอร์สทั้งหมดใน node_modules/@types พร้อมกัน แท้จริงแล้ว ถ้าฉันลบโฟลเดอร์ node_modules/@types/webdriverio ออกและรัน tsc อีกครั้ง ฉันก็จะไม่พบข้อผิดพลาด (แน่นอน ตราบใดที่ฉันยังคงคอมเมนต์โค้ดทดสอบอยู่)

นี่คือไฟล์ tsconfig.json ของฉันซึ่งอยู่ในโฟลเดอร์รากของโปรเจกต์:

{
    "compilerOptions": {
        "target": "ES6",
        "module": "commonjs",
        "sourceMap": false,
        "inlineSourceMap": true,
        "inlineSources": true,
        "declaration": false,
        "outDir": "dist"
    },
    "include": [
        "src/**/*"
    ]
}

ซอร์สโค้ดทั้งหมดของฉันอยู่ในไดเรกทอรี src การทดสอบอยู่ใน src/test

มีการตั้งค่าใดบ้างที่ฉันสามารถทำเพื่อให้ประเภทของ webdriverio และ jquery แยกออกจากกันในเวลาคอมไพล์? นอกจากนี้ ฉันยังเคยเห็นตัวอย่างโค้ดที่เขียนเป็น js ที่ใช้ทั้งสองพร้อมกัน: สิ่งนี้ไม่สามารถทำได้ใน typescript หรือ?

คำตอบ #1

มันนานมากแล้ว แต่ฉันพบวิธีแก้ปัญหาแล้ว!

คุณจำเป็นต้องกำหนด tsconfig สองชุดแยกกัน: หนึ่งชุดสำหรับโปรเจกต์หลักและอีกหนึ่งชุดสำหรับการทดสอบ

tsconfig.project.json

{
    "compilerOptions": {
        "target": "ES6",
        "module": "commonjs",
        "sourceMap": false,
        "inlineSourceMap": true,
        "inlineSources": true,
        "watch": false,
        "declaration": false,
        "outDir": "dist",
        "typeRoots": ["./typings"],
    },
    "include": [
        "src/**/*"
    ],
    "exclude": [
        "src/test/*"
    ]
}

tsconfig.test.json

{
    "compilerOptions": {
        "target": "ES6",
        "module": "commonjs",
        "sourceMap": false,
        "inlineSourceMap": true,
        "inlineSources": true,
        "watch": false,
        "declaration": false,
        "outDir": "dist",
        "typeRoots": ["./typings"],
    },
    "include": [
        "src/test/*"
    ]
}

จากนั้น ในไฟล์ package.json ให้กำหนดสคริปต์สองตัวที่แตกต่างกันเพื่อรัน tsc กับ tsconfig สองตัวที่คุณเพิ่งกำหนดไว้:

{
...
  "scripts": {
    "test": "tsc -p tsconfig.test.json && mocha --exit dist/test",
    "tsc": "tsc -p tsconfig.project.json",
    ...
  },
...
}

ประเด็นสำคัญคือการกำหนดค่า typeRoots ซึ่งเขียนทับพฤติกรรมเริ่มต้นของคอมไพเลอร์ TypeScript พฤติกรรมเริ่มต้นคือการโหลดทุกแพ็กเกจที่กำหนดไว้ภายใต้โฟลเดอร์ @types ใด ๆ (ดังนั้นทุก @types ที่ติดตั้งในโฟลเดอร์ node_modules จะถูกนำมารวม) โดยการเขียนทับการกำหนดค่านี้ @types ใน node_modules จะถูกรวมเฉพาะเมื่อมีการอ้างอิง หรือคุณสามารถแทนที่การกำหนดค่า typeRoots ด้วย

"types": []

จาก https://www.typescriptlang.org/docs/handbook/tsconfig-json.html

@types, typeRoots และ types

โดยดีฟอลต์ แพ็กเกจ "@types" ที่มองเห็นทั้งหมดจะถูกรวมอยู่ในการคอมไพล์ของคุณ แพ็กเกจใน node_modules/@types ของโฟลเดอร์ใด ๆ ที่ครอบคลุมถือว่ามองเห็นได้; โดยเฉพาะหมายถึงแพ็กเกจภายใน ./node_modules/@types/, ../node_modules/@types/, ../../node_modules/@types/ และอื่น ๆ ต่อไป

หากระบุ typeRoots จะรวมเฉพาะแพ็กเกจที่อยู่ใต้ typeRoots เท่านั้น

...

ระบุ "types": [] เพื่อปิดการรวมแพ็กเกจ @types อัตโนมัติ

จำไว้ว่าการรวมอัตโนมัติมีความสำคัญก็ต่อเมื่อคุณกำลังใช้ไฟล์ที่มีการประกาศแบบทั่วโลก (ตรงข้ามกับไฟล์ที่ประกาศเป็นโมดูล). ตัวอย่างเช่น หากคุณใช้คำสั่ง import "foo", TypeScript อาจยังคงค้นหาผ่านโฟลเดอร์ node_modules และ node_modules/@types เพื่อค้นหาแพ็กเกจ foo.

อีกประเด็นสำคัญคือการแยกไฟล์คอนฟิก ด้วยวิธีนี้คุณสามารถยกเว้นไฟล์ทดสอบเมื่อคอมไพล์โปรเจกต์หลักและในทางกลับกัน สิ่งนี้สำคัญเพราะโปรเจกต์หลักรวม jquery ในขณะที่ไฟล์ทดสอบรวม webdriverio การคอมไพล์พวกมันรวมกันคุณจะได้ข้อผิดพลาดเหมือนกับที่อธิบายในคำถาม

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