น่าเสียดายที่สิ่งเหล่านี้ยังไม่ได้รับการบันทึกไว้เป็นอย่างดีในขณะนี้ แต่แม้ว่าคุณจะสามารถทำให้มันใช้งานได้ แต่เรามาดูการกำหนดค่าของคุณกันดีกว่าเพื่อที่คุณจะได้เข้าใจว่าแต่ละส่วนกำลังทำอะไรอยู่และเกี่ยวข้องกับวิธีการประมวลผล 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
, และpaths
moduleResolution
โดยทั่วไปเมื่อใช้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'
จากนั้นหากไม่พบให้ลองอีกครั้งโดยไม่มีคำนำหน้า (รายการที่สองในอาร์เรย์เป็นเพียง*
ซึ่งหมายถึงการนำเข้าเริ่มต้น
ดังนั้นวิธีนี้คุณสามารถเพิ่มโฟลเดอร์เพิ่มเติมในการค้นหาไฟล์ประกาศกำหนดเองหรือแม้กระทั่งที่กำหนดเองโมดูลที่คุณต้องการเพื่อให้สามารถ.ts
import
คุณยังสามารถสร้างการแมปที่กำหนดเองสำหรับโมดูลเฉพาะ:
"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
วัตถุประสงค์ของการพิมพ์อย่างไร?