टाइपस्क्रिप्ट 2: अप्रयुक्त एनपीएम मॉड्यूल के लिए कस्टम टाइपिंग


93

में पोस्ट किए गए सुझावों की कोशिश करने के बाद अन्य स्थानों पर , मैं खुद को एक टाइपस्क्रिप्ट प्रोजेक्ट प्राप्त करने में असमर्थ पाता हूं जो एक अप्रकाशित एनपीएम मॉड्यूल का उपयोग करता है। नीचे एक न्यूनतम उदाहरण और मेरे द्वारा उठाए गए कदम हैं।

इस न्यूनतम उदाहरण के लिए, हम दिखावा करेंगे कि lodashमौजूदा प्रकार की परिभाषाएँ नहीं हैं। जैसे, हम पैकेज की अनदेखी करेंगे@types/lodash और इसकी टाइपिंग फ़ाइल lodash.d.tsको अपने प्रोजेक्ट में मैन्युअल रूप से जोड़ने का प्रयास ।

फ़ोल्डर संरचना

  • node_modules
    • lodash
  • src
    • foo.ts
  • typings
    • रिवाज
      • lodash.d.ts
    • वैश्विक
    • index.d.ts
  • package.json
  • tsconfig.json
  • typings.json

अगला, फ़ाइलें।

फ़ाइल foo.ts

///<reference path="../typings/custom/lodash.d.ts" />
import * as lodash from 'lodash';

console.log('Weeee');

फ़ाइल lodash.d.tsको मूल @types/lodashपैकेज से सीधे कॉपी किया जाता है ।

फ़ाइल index.d.ts

/// <reference path="custom/lodash.d.ts" />
/// <reference path="globals/lodash/index.d.ts" />

फ़ाइल package.json

{
  "name": "ts",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "typings": "./typings/index.d.ts",
  "dependencies": {
    "lodash": "^4.16.4"
  },
  "author": "",
  "license": "ISC"
}

फ़ाइल tsconfig.json

{
  "compilerOptions": {
    "target": "ES6",
    "jsx": "react",
    "module": "commonjs",
    "sourceMap": true,
    "noImplicitAny": true,
    "experimentalDecorators": true,
    "typeRoots" : ["./typings"],
    "types": ["lodash"]
  },
  "include": [
    "typings/**/*",
    "src/**/*"
  ],
  "exclude": [
    "node_modules",
    "**/*.spec.ts"
  ]
}

फ़ाइल typings.json

{
    "name": "TestName",
    "version": false,
    "globalDependencies": {
        "lodash": "file:typings/custom/lodash.d.ts"
    }
}

जैसा कि आप देख सकते हैं, मैंने टाइपिंग आयात करने के कई अलग-अलग तरीकों की कोशिश की है:

  1. सीधे इसमें आयात करके foo.ts
  2. में एक typingsसंपत्ति द्वाराpackage.json
  3. का उपयोग करके typeRootsमें tsconfig.jsonएक फ़ाइल के साथtypings/index.d.ts
  4. एक स्पष्ट का उपयोग करके typesमेंtsconfig.json
  5. में typesनिर्देशिका को शामिल करकेtsconfig.json
  6. एक कस्टम typings.jsonफ़ाइल बनाकर और चलाकरtypings install

फिर भी, जब मैं टाइपस्क्रिप्ट चलाता हूं:

E:\temp\ts>tsc
error TS2688: Cannot find type definition file for 'lodash'.

मैं क्या गलत कर रहा हूं?

जवाबों:


202

दुर्भाग्य से ये चीजें वर्तमान में बहुत अच्छी तरह से प्रलेखित नहीं हैं, लेकिन भले ही आप इसे काम करने में सक्षम थे, चलो अपने कॉन्फ़िगरेशन पर जाएं ताकि आप समझ सकें कि प्रत्येक भाग क्या कर रहा है और यह कैसे टाइपस्क्रिप्ट प्रक्रियाओं और टाइपिंग लोड करने से संबंधित है।

पहले आप जो त्रुटि प्राप्त कर रहे हैं, उस पर चलें:

error TS2688: Cannot find type definition file for 'lodash'.

यह त्रुटि वास्तव में आपके ts फ़ाइलों में कहीं भी अपने आयात या संदर्भ या अपने रिकॉर्ड को उपयोग करने के प्रयास से नहीं आ रही है। बल्कि यह गलतफहमी से आ रहा है कि गुणों typeRootsऔर typesगुणों का उपयोग कैसे किया जाए, तो चलिए उन पर थोड़ा और विस्तार करते हैं।

typeRoots:[]और types:[]गुणों के बारे में बात यह है कि वे मनमाने ढंग से घोषणा ( ) फ़ाइलों को लोड करने के लिए सामान्य-उद्देश्य तरीके नहीं हैं *.d.ts

ये दो गुण सीधे नई टीएस 2.0 सुविधा से संबंधित हैं जो एनपीएम पैकेज से पैकेजिंग और लोडिंग टाइपिंग घोषणाओं की अनुमति देता है

यह समझना बहुत महत्वपूर्ण है, कि ये केवल एनपीएम प्रारूप में फ़ोल्डर के साथ काम करते हैं (अर्थात एक पैकेज से युक्त फ़ोल्डर । json या index.dts ।)।

इसके लिए डिफ़ॉल्ट typeRootsहै:

{
   "typeRoots" : ["node_modules/@types"]
}

डिफ़ॉल्ट रूप से इसका मतलब यह है कि टाइपस्क्रिप्ट node_modules/@typesफ़ोल्डर में जाएगा और प्रत्येक उप-फ़ोल्डर को लोड करने का प्रयास करेगा जो इसे npm पैकेज के रूप में मिलता है ।

यह समझना महत्वपूर्ण है कि यह विफल हो जाएगा यदि किसी फ़ोल्डर में एनपीएम पैकेज जैसी संरचना नहीं है।

यह आपके मामले में हो रहा है, और आपकी प्रारंभिक त्रुटि का स्रोत है।

आपने टाइप किया है टाइप करें:

{
    "typeRoots" : ["./typings"]
}

इसका अर्थ है कि टाइपस्क्रिप्ट अब सबफ़ोल्डर के./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']आप जिस प्रॉपर्टी को सेट कर रहे हैं, उसके बारे में थोड़ा बात करते हैं। यह क्या करता है? डिफ़ॉल्ट रूप से, टाइपस्क्रिप्ट सभी उप-फ़ोल्डर्स को लोड करेगा जो आपके भीतर पाता है typeRoots। यदि आप एक types:संपत्ति निर्दिष्ट करते हैं तो यह केवल उन विशिष्ट उप-फ़ोल्डरों को लोड करेगा।

आपके मामले में आप इसे ./typings/lodashफ़ोल्डर को लोड करने के लिए कह रहे हैं लेकिन यह मौजूद नहीं है। यही कारण है कि आप प्राप्त करते हैं:

error TS2688: Cannot find type definition file for 'lodash'

तो आइए संक्षेप में जानें कि हमने क्या सीखा है। टाइपस्क्रिप्ट 2.0 पेश किया typeRootsऔर npm संकुलtypes में पैक की गई घोषणा फाइलों को लोड करने के लिए । यदि आपके पास कस्टम टाइपिंग या एकल ढीली d.tsफाइलें हैं जो npm पैकेज सम्मेलनों के बाद एक फ़ोल्डर के साथ समाहित नहीं हैं, तो ये दो नए गुण हैं जो आप उपयोग नहीं करना चाहते हैं। टाइपस्क्रिप्ट 2.0 वास्तव में नहीं बदलता है कि इनका सेवन कैसे किया जाएगा। आपको इन फ़ाइलों को अपने संकलन संदर्भ में कई मानक तरीकों में शामिल करना होगा:

  1. सीधे इसमें एक .ts फ़ाइल : ///<reference path="../typings/custom/lodash.d.ts" />

  2. समेत ./typings/custom/lodash.d.tsअपनी files: []संपत्ति में ।

  3. समेत ./typings/index.d.ts अपने में files: []संपत्ति (जो तब रिकर्सिवली अन्य typings भी शामिल है।

  4. जोड़ा जा रहा है ./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


1
आपके विस्तृत उत्तर के लिए धन्यवाद। यह अलगाव में समाधान का काम करता है, लेकिन वे अच्छी तरह से मिश्रण नहीं करते हैं। यह चीजों को स्पष्ट करता है इसलिए मैं आपको इनाम दूंगा। यदि आपको कुछ और बिंदुओं का जवाब देने का समय मिल सकता है, तो यह वास्तव में अन्य लोगों के लिए सहायक हो सकता है। (1) टाइपरूट्स के लिए केवल एक विशिष्ट फ़ोल्डर संरचना को स्वीकार करने का कोई कारण है? यह मनमाना लगता है। (2) अगर मैं टाइप-रूट्स में बदलाव करता हूं, तो टाइपस्क्रिप्ट में अभी भी नोड में @types फोल्डर शामिल हैं, जो कि स्पेक के विपरीत है। (३) टाइपिंग के उद्देश्य pathsसे क्या और कैसे अलग है include?
जोड़ीयुग

1
मैंने जवाब संपादित किया, मुझे बताएं कि क्या आपके पास कोई और प्रश्न है।
dtabuenc

1
धन्यवाद, मैंने बाकी पढ़ा और वाह। इस सब को खोजने के लिए आपको सहारा देता है। ऐसा लग रहा है कि यहां काम पर बहुत अनावश्यक रूप से जटिल व्यवहार है। मुझे आशा है कि टाइपस्क्रिप्ट भविष्य में उनके विन्यास गुणों को थोड़ा अधिक स्व-दस्तावेजीकरण कर देगा।
जोड़ी


2
क्या अंतिम उदाहरण नहीं होना चाहिए "paths" :{ "my-types": ["some/custom/folder/location/my-awesome-types-file"] }?
कोएन।

6

संपादित करें: पुराना ऊपर जवाब पढ़ें।

मुझे अभी भी यह समझ में नहीं आया है, लेकिन मुझे एक समाधान मिला। निम्नलिखित का उपयोग करें tsconfig.json:

{
  "compilerOptions": {
    "target": "ES6",
    "jsx": "react",
    "module": "commonjs",
    "sourceMap": true,
    "noImplicitAny": true,
    "experimentalDecorators": true,
    "baseUrl": ".",
    "paths": {
      "*": [
        "./typings/*"
      ]
    }
  },
  "include": [
    "src/**/*"
  ],
  "exclude": [
    "node_modules",
    "**/*.spec.ts"
  ]
}

निकालें typings.jsonऔर फ़ोल्डर के तहत सब कुछ typingsछोड़करlodash.d.ts । सभी ///...संदर्भ भी निकालें


3

"*": ["./types/*"] Tsconfig रास्तों में इस लाइन ने 2 घंटे के संघर्ष के बाद सब कुछ तय कर दिया।

{
  "compilerOptions": {
    "moduleResolution": "node",
    "strict": true,
    "baseUrl": ".",
    "paths": {
      "*": ["./types/*"]
    },
    "jsx": "react",
    "types": ["node", "jest"]
  },
  "include": [
    "client/**/*",
    "packages/**/*"
  ],
  "exclude": [
    "node_modules/**/*"
  ]
}

प्रकार फ़ोल्डर का नाम है, जो क्लाइंट फ़ोल्डर (या src फ़ोल्डर) types/third-party-lib/index.d.ts
index.dts के स्तर में node_module के पास बैठता है।declare module 'third-party-lib';

नोट: उपरोक्त विन्यास एक अधूरा विन्यास है, बस यह अंदाजा लगाने के लिए कि यह किस प्रकार, पथों के साथ कैसा दिखता है, इसमें शामिल है और बाहर है।


1

मुझे पता है कि यह एक पुराना प्रश्न है, लेकिन टाइपस्क्रिप्ट टूलिंग लगातार बदलती रही है। मुझे लगता है कि इस बिंदु पर सबसे अच्छा विकल्प सिर्फ tsconfig.json में "शामिल" पथ सेटिंग्स पर निर्भर है।

  "include": [
        "src/**/*"
    ],

डिफ़ॉल्ट रूप से, जब तक कि आप विशेष परिवर्तन नहीं करते हैं, सभी * .ts और सभी * .d.ts फ़ाइलों को src/स्वचालित रूप से शामिल किया जाएगा। मुझे लगता है कि यह कस्टमाइज़िंग के बिना कस्टम प्रकार की घोषणा फ़ाइलों को शामिल करने का सबसे आसान / सबसे अच्छा तरीका है typeRootsऔरtypes

संदर्भ:


0

हम अपने हालिया अवलोकन में से कुछ को साझा करना चाहते हैं ताकि हम ऊपर दिए गए विस्तृत विवरण का विस्तार कर सकें । पहले यह नोट करना महत्वपूर्ण है कि वीएस कोड में अक्सर अलग-अलग राय होती है कि चीजों को कैसे करना है।

एक उदाहरण देखिए मैंने हाल ही में काम किया है:

src / ऐप्स / घटकों / भूखंड-plotly / भूखंड-plotly.component.ts:

/// <reference types="plotly.js" />
import * as Plotly from 'plotly.js';

VS कोड की शिकायत हो सकती है: No need to reference "plotly.js", since it is imported. (no-reference import) tslint(1)

मामले में हम त्रुटि के बिना संकलित परियोजना शुरू करते हैं, लेकिन अगर हम उस पंक्ति को हटा दें तो प्रारंभ के दौरान निम्नलिखित त्रुटि दिखाई देगी:

ERROR in src/app/components/plot-plotly/plot-plotly.component.ts:19:21 - error TS2503: Cannot find namespace 'plotly'.

वही त्रुटि संदेश दिखाई देता है जिस स्थिति में हम रखते हैं reference types आयात विवरणों के बाद निर्देश ।

महत्वपूर्ण : /// <reference types="plotly.js" />प्रकार स्क्रिप्ट फ़ाइल के सामने होना चाहिए! संबंधित दस्तावेज देखें: लिंक

ट्रिपल-स्लैश निर्देश केवल उनकी युक्त फ़ाइल के शीर्ष पर मान्य हैं।

मैं भी tsconfig.json और typeRoot अनुभाग: लिंक पर प्रलेखन पढ़ने की सलाह देता हूं

एक प्रकार का पैकेज एक फ़ोल्डर है, जिसमें index.d.ts नामक फ़ाइल या एक पैकेज के साथ एक फ़ोल्डर होता है। इसमें एक प्रकार का फ़ील्ड होता है।

उपरोक्त संदर्भ निर्देश निम्नलिखित परिदृश्य में काम करता है:

प्रकार / प्लॉटली। js / index.d.ts: ( लिंक )

  declare namespace plotly {
    export interface ...
  }

तथा

tsconfig.json:

  "compilerOptions": {
    ...
    "typeRoots": [
      "types/",
      "node_modules/@types"
    ],
    ...  

नोट : उपरोक्त सेटअप में दो "प्लाट्ली.जेएस" का अर्थ है दो अलग-अलग फ़ोल्डर और फाइलें (लाइब्रेरी / परिभाषा)। आयात "node_modules / plotly.js" फ़ोल्डर (द्वारा जोड़ा गया) पर लागू होता हैnpm install plotly.js ) पर लागू होता है, जबकि संदर्भ प्रकार / plotly.js पर लागू होता है।

वीएस कोड को हल करने की मेरी परियोजना के लिए शिकायत और "दो" की अस्पष्टता की साजिश है। जेएस, मैं निम्नलिखित कॉन्फ़िगरेशन के साथ समाप्त हुआ:

  • सभी फ़ाइल मूल स्थान पर बने रहे
  • tsconfig.json:
  "compilerOptions": {
    ...
    "typeRoots": [
      "./",
      "node_modules/@types"
    ],
    ...  
  • src / ऐप्स / घटकों / भूखंड-plotly / भूखंड-plotly.component.ts:
  /// <reference types="types/plotly.js" />
  import * as Plotly from 'plotly.js';

  plotDemo() {

  // types using plotly namespace
  const chunk: plotly.traces.Scatter = {
      x: [1, 2, 3, 4, 5],
      y: [1, 3, 2, 3, 1],
      mode: 'lines+markers',
      name: 'linear',
      line: { shape: 'linear' },
      type: 'scatter'
  };

  // module call using Plotly module import
  Plotly.newPlot(...);
  }

मेरे सिस्टम पर DevDeps:

  • "ts-node": "~ 8.3.0",
  • "tslint": "~ 5.18.0",
  • "टाइपस्क्रिप्ट": "~ 3.7.5"
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.