น่าเสียดายที่สิ่งเหล่านี้ยังไม่ได้รับการบันทึกไว้เป็นอย่างดีในขณะนี้ แต่แม้ว่าคุณจะสามารถทำให้มันใช้งานได้ แต่เรามาดูการกำหนดค่าของคุณกันดีกว่าเพื่อที่คุณจะได้เข้าใจว่าแต่ละส่วนกำลังทำอะไรอยู่และเกี่ยวข้องกับวิธีการประมวลผล typescript และโหลดการพิมพ์
ก่อนอื่นเรามาดูข้อผิดพลาดที่คุณได้รับ:
error TS2688: Cannot find type definition file for 'lodash'.
ข้อผิดพลาดนี้ไม่ได้มาจากการนำเข้าหรือการอ้างอิงของคุณหรือความพยายามของคุณที่จะใช้ lodash ที่ใดก็ได้ในไฟล์ ts ของคุณ ค่อนข้างจะมาจากความเข้าใจผิดเกี่ยวกับวิธีการใช้typeRootsและtypesคุณสมบัติดังนั้นเรามาดูรายละเอียดเพิ่มเติมเล็กน้อยเกี่ยวกับสิ่งเหล่านี้
สิ่งที่เกี่ยวกับtypeRoots:[]และtypes:[]คุณสมบัติคือไม่ใช่วิธีที่มีวัตถุประสงค์ทั่วไปในการโหลด*.d.tsไฟล์การประกาศโดยพลการ ( )
คุณสมบัติทั้งสองนี้จะเกี่ยวข้องโดยตรงกับ TS ใหม่ 2.0 คุณสมบัติที่ช่วยให้บรรจุภัณฑ์และการพิมพ์โหลดประกาศจากแพคเกจ NPM
สิ่งนี้สำคัญมากที่ต้องเข้าใจว่าสิ่งเหล่านี้ใช้ได้กับโฟลเดอร์ในรูปแบบ NPM เท่านั้น (เช่นโฟลเดอร์ที่มีpackage.jsonหรือindex.d.ts )
ค่าเริ่มต้นtypeRootsคือ:
{
"typeRoots" : ["node_modules/@types"]
}
โดยค่าเริ่มต้นนี้หมายความว่า typescript จะไปลงในnode_modules/@typesโฟลเดอร์และพยายามที่จะโหลดทุกโฟลเดอร์ย่อยที่พบมีเป็นแพคเกจ NPM
สิ่งสำคัญคือต้องเข้าใจว่าสิ่งนี้จะล้มเหลวหากโฟลเดอร์ไม่มีโครงสร้างเหมือนแพ็คเกจ npm
นี่คือสิ่งที่เกิดขึ้นในกรณีของคุณและที่มาของข้อผิดพลาดเริ่มต้นของคุณ
คุณได้เปลี่ยน typeRoot เป็น:
{
"typeRoots" : ["./typings"]
}
ซึ่งหมายความว่า typescript จะสแกน./typingsโฟลเดอร์เพื่อหาโฟลเดอร์ย่อยและพยายามโหลดโฟลเดอร์ย่อยแต่ละโฟลเดอร์ที่พบว่าเป็นโมดูล npm
สมมติว่าคุณเพิ่งtypeRootsตั้งค่าให้ชี้ไปที่./typingsแต่ยังไม่มีtypes:[]การตั้งค่าคุณสมบัติใด ๆ คุณน่าจะเห็นข้อผิดพลาดเหล่านี้:
error TS2688: Cannot find type definition file for 'custom'.
error TS2688: Cannot find type definition file for 'global'.
เนื่องจากtscกำลังสแกน./typingsโฟลเดอร์ของคุณและค้นหาโฟลเดอร์ย่อยcustomและglobal. จากนั้นพยายามตีความสิ่งเหล่านี้เป็นการพิมพ์ประเภทแพ็คเกจ npm แต่ไม่มีindex.d.tsหรือpackage.jsonในโฟลเดอร์เหล่านี้คุณจึงได้รับข้อผิดพลาด
ตอนนี้เรามาพูดถึงtypes: ['lodash']คุณสมบัติที่คุณกำลังตั้งค่ากัน สิ่งนี้ทำอะไร? โดยค่าเริ่มต้น typescript จะโหลดโฟลเดอร์ย่อยทั้งหมดที่พบในtypeRootsไฟล์. หากคุณระบุtypes:คุณสมบัติมันจะโหลดเฉพาะโฟลเดอร์ย่อยเหล่านั้นเท่านั้น
ในกรณีของคุณคุณกำลังบอกให้โหลด./typings/lodashโฟลเดอร์ แต่ไม่มีอยู่ นี่คือเหตุผลที่คุณได้รับ:
error TS2688: Cannot find type definition file for 'lodash'
ลองสรุปสิ่งที่เราได้เรียนรู้ typescript 2.0 แนะนำtypeRootsและtypesสำหรับการโหลดไฟล์ประกาศบรรจุในแพคเกจ NPM หากคุณมีการพิมพ์แบบกำหนดเองหรือd.tsไฟล์แบบหลวม ๆ เพียงไฟล์เดียวที่ไม่ได้อยู่ในโฟลเดอร์ตามข้อกำหนดแพ็คเกจ npm คุณสมบัติใหม่ทั้งสองนี้ไม่ใช่สิ่งที่คุณต้องการใช้ typescript 2.0 ไม่ได้เปลี่ยนวิธีการใช้งานสิ่งเหล่านี้ คุณต้องรวมไฟล์เหล่านี้ไว้ในบริบทการคอมไพล์ของคุณด้วยวิธีมาตรฐานอย่างใดอย่างหนึ่ง:
รวมไว้ใน.tsไฟล์โดยตรง:
///<reference path="../typings/custom/lodash.d.ts" />
รวมทั้ง./typings/custom/lodash.d.tsในfiles: []ทรัพย์สินของคุณ
รวมถึง./typings/index.d.tsในfiles: []ทรัพย์สินของคุณ(ซึ่งจะรวมการพิมพ์อื่น ๆ ซ้ำ ๆ
การเพิ่ม./typings/**ของคุณincludes:
หวังว่าจากการสนทนานี้คุณจะสามารถบอกได้ว่าเหตุใดการเปลี่ยนแปลงที่คุณtsconfig.jsonทำกับสิ่งที่คุณทำไว้จึงกลับมาใช้ได้อีกครั้ง
แก้ไข:
สิ่งหนึ่งที่ฉันลืมพูดถึงคือtypeRootsและtypesคุณสมบัติมีประโยชน์จริงๆสำหรับการโหลดการประกาศทั่วโลกโดยอัตโนมัติ
ตัวอย่างเช่นถ้าคุณ
npm install @types/jquery
และคุณกำลังใช้ tsconfig เริ่มต้นแพ็คเกจประเภท jquery นั้นจะถูกโหลดโดยอัตโนมัติและ$จะพร้อมใช้งานตลอดทั้งสคริปต์ของคุณโดยไม่ต้องดำเนินการใด ๆ เพิ่มเติม///<reference/>หรือimport
typeRoots:[]คุณสมบัติจะหมายถึงการเพิ่มสถานที่เพิ่มเติมจากที่ประเภทแพคเกจจะถูกโหลด frrom โดยอัตโนมัติ
types:[]กรณีการใช้งานหลักของโรงแรมคือการปิดพฤติกรรมการโหลดอัตโนมัติ (โดยการตั้งค่าให้กับอาร์เรย์ว่างเปล่า) และหลังจากนั้นเพียงรายการเฉพาะประเภทที่คุณต้องการรวมทั่วโลก
อีกวิธีหนึ่งในการโหลดแพ็กเกจประเภทต่างๆtypeRootsคือการใช้///<reference types="jquery" />คำสั่งใหม่ สังเกตtypesแทนpath. import/exportอีกครั้งนี้จะเป็นประโยชน์สำหรับไฟล์ประกาศทั่วโลกโดยทั่วไปแล้วคนที่ไม่ได้ทำ
typeRootsตอนนี้ที่นี่เป็นหนึ่งในสิ่งที่ทำให้เกิดความสับสนกับ จำไว้ว่าฉันพูดว่านั่นtypeRootsเกี่ยวกับการรวมโมดูลทั่วโลก แต่@types/folderยังเกี่ยวข้องกับความละเอียดโมดูลมาตรฐาน (ไม่ว่าคุณจะtypeRootsตั้งค่าแบบใด)
โดยเฉพาะการนำเข้าโมดูลอย่างชัดเจนเสมอทะลุทั้งหมด includes, excludes, files, typeRootsและtypesตัวเลือก ดังนั้นเมื่อคุณทำ:
import {MyType} from 'my-module';
คุณสมบัติที่กล่าวมาทั้งหมดจะถูกละเว้นโดยสิ้นเชิง คุณสมบัติที่มีความเกี่ยวข้องระหว่างความละเอียดโมดูลมีbaseUrl, และpathsmoduleResolution
โดยทั่วไปเมื่อใช้nodeความละเอียดโมดูลก็จะเริ่มต้นการค้นหาสำหรับชื่อไฟล์my-module.ts, my-module.tsx, my-module.d.tsเริ่มต้นที่โฟลเดอร์ที่ชี้ไปตามที่คุณbaseUrlกำหนดค่า
หากไม่พบไฟล์ก็จะมองหาโฟลเดอร์ที่มีชื่อmy-moduleแล้วค้นหาpackage.jsonด้วยtypingsคุณสมบัติหากมีpackage.jsonหรือไม่มีtypingsคุณสมบัติอยู่ข้างในบอกว่าจะโหลดไฟล์ใดจากนั้นจะค้นหาindex.ts/tsx/d.tsภายในโฟลเดอร์นั้น
หากยังไม่สำเร็จก็จะค้นหาสิ่งเดียวกันนี้ในnode_modulesโฟลเดอร์โดยเริ่มจากbaseUrl/node_modulesไฟล์.
นอกจากนี้หากไม่พบสิ่งเหล่านี้ก็จะค้นหาbaseUrl/node_modules/@typesสิ่งที่เหมือนกันทั้งหมด
หากยังไม่พบสิ่งใดมันจะเริ่มไปที่ไดเรกทอรีหลักและค้นหาnode_modulesและที่node_modules/@typesนั่น มันจะขึ้นไดเร็กทอรีไปเรื่อย ๆ จนกว่าจะถึงรูทของระบบไฟล์ของคุณ (แม้กระทั่งรับโหนดโมดูลนอกโปรเจ็กต์ของคุณ)
สิ่งหนึ่งที่ฉันต้องการเน้นคือความละเอียดของโมดูลจะไม่สนใจสิ่งที่typeRootsคุณตั้งไว้โดยสิ้นเชิง ดังนั้นหากคุณกำหนดค่าtypeRoots: ["./my-types"]สิ่งนี้จะไม่ถูกค้นหาในระหว่างการแก้ปัญหาโมดูลอย่างชัดเจน ทำหน้าที่เป็นโฟลเดอร์ที่คุณสามารถใส่ไฟล์ความคมชัดส่วนกลางที่คุณต้องการให้ใช้ได้กับแอปพลิเคชันทั้งหมดโดยไม่ต้องนำเข้าหรืออ้างอิง
สุดท้ายคุณสามารถแทนที่ลักษณะการทำงานของโมดูลด้วยการแมปพา ธ (เช่นpathsคุณสมบัติ) ตัวอย่างเช่นฉันกล่าวว่าtypeRootsไม่มีการพิจารณากำหนดเองใด ๆเมื่อพยายามแก้ไขโมดูล แต่ถ้าคุณชอบคุณสามารถทำให้พฤติกรรมนี้เกิดขึ้นได้:
"paths" :{
"*": ["my-custom-types/*", "*"]
}
สิ่งนี้ใช้สำหรับการนำเข้าทั้งหมดที่ตรงกับด้านซ้ายมือลองแก้ไขการนำเข้าเช่นเดียวกับทางด้านขวาก่อนที่จะลองรวมเข้าด้วยกัน ( *ทางด้านขวามือแสดงถึงสตริงการนำเข้าเริ่มต้นของคุณตัวอย่างเช่นหากคุณนำเข้า:
import {MyType} from 'my-types';
ขั้นแรกให้ลองนำเข้าเหมือนที่คุณเขียน:
import {MyType} from 'my-custom-types/my-types'
จากนั้นหากไม่พบให้ลองอีกครั้งโดยไม่มีคำนำหน้า (รายการที่สองในอาร์เรย์เป็นเพียง*ซึ่งหมายถึงการนำเข้าเริ่มต้น
ดังนั้นวิธีนี้คุณสามารถเพิ่มโฟลเดอร์เพิ่มเติมในการค้นหาไฟล์ประกาศกำหนดเองหรือแม้กระทั่งที่กำหนดเองโมดูลที่คุณต้องการเพื่อให้สามารถ.tsimport
คุณยังสามารถสร้างการแมปที่กำหนดเองสำหรับโมดูลเฉพาะ:
"paths" :{
"*": ["my-types", "some/custom/folder/location/my-awesome-types-file"]
}
สิ่งนี้จะช่วยให้คุณทำ
import {MyType} from 'my-types';
แต่อ่านประเภทเหล่านั้นจาก some/custom/folder/location/my-awesome-types-file.d.ts
pathsและแตกต่างจากincludeวัตถุประสงค์ของการพิมพ์อย่างไร?