node.js - TypeScript importeren uit externe node-modules
Ik wil mijn applicatie opsplitsen in verschillende node-modules en een hoofdmodule hebben die alle andere modules ook bouwt, en ik wil TypeScript gebruiken met ES6-modules.
Hier is mijn geplande projectstructuur:
main
node_modules
- dep-a
- node_modules
- dep-a
- dep-b
raamwerk
interfaces
- IComponent.ts
dep-a
componenten
- test.ts
node_modules
- raamwerk
dep-b
node_modules
- raamwerk
Ik wil in staat zijn om interfaces te definiëren in het framework die kunnen worden gebruikt in dep-a, dep-b en main.
Hoe stel ik dit correct in? Kan ik alles compileren vanuit mijn hoofdmodule? Moet ik verschillende bundels maken voor framework, dep-a, ... en een ander typebestand? Wat is de beste aanpak hiervoor?
Ik heb al wat testbestanden en mappen opgezet en heb npm link gebruikt om de afhankelijkheden te koppelen en webpack om de bestanden te bundelen, en ik loop altijd tegen problemen aan waarbij bestanden niet worden gevonden:
error TS2307: Cannot find module 'framework/interfaces/IComponent'
en
Module not found: Error: Cannot resolve 'file' or 'directory' ./components/test
Antwoord #1
TL;DR genereer declaraties voor de modules met declaration: true in tsconfig.json en specificeer het bestand voor je gegenereerde typings in de typings vermeldingssectie van het package.json bestand
raamwerk
Gebruik een tsconfig-bestand dat hierop lijkt:
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"declaration": true,
"noImplicitAny": true,
"removeComments": true,
"outDir": "dist",
...
},
"files": [
...
]
}
Het belangrijke stukje is declaration: true wat interne declaraties zal genereren in de dist-map
Aangenomen dat er een index.ts-bestand is dat alle interessante onderdelen van framework (her)exporteert, maak een package.json-bestand met een main- en typings-vermelding die respectievelijk verwijzen naar de gegenereerde js en de gegenereerde declaratie, dat wil zeggen
{
"name": "framework",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
...
}
Commit deze module naar een git-repository, bijvoorbeeld Bitbucket op: "https://[email /myUser/framework.git"
dep-a
in package.json een afhankelijkheid aan framework maken
{
"dependencies": {
"framework": "https://[email /myUser/framework.git"
},
}
Dat is het.
import * from 'framework'
zal de afhankelijkheid met de typings automatisch ophalen
Het is duidelijk mogelijk om met dep-a te doen wat met framework is gedaan, d.w.z. de declaraties genereren, package.json bijwerken en dep-a gebruiken als een module met ingebedde typings in main
opmerking: een bestands-URL volstaat in package.json/dependencies als je niet via een externe git-repo wilt gaan
Antwoord #2
Wat arriveerde in TypeScript 1.6 is de typings eigenschap in het package.json module. Je kunt het relevante issue op GitHub bekijken.
Dus aangenomen dat je aparte modules wilt maken (dep-a, framework). Je kunt het volgende doen:
main.ts // (1)
package.json // (2)
node_modules/
dep_a/
index.js // (3)
index.d.ts // (4)
package.json // (5)
node_modules/
framework/
index.js // (6)
index.d.ts // (7)
package.json // (8)
Laten we dus eens kijken wat je in je bestanden hebt :
//(1) main.ts
import * as depA from "depA";
console.log(depA({ a : true, b : 2 }) === true) // true;
//(2) package.json
{
name: "main",
dependencies: {
"dep_a" : "0.0.1"
}
...
}
Voor depA
//(3) dep_a/index.js
module.exports = function a(options) { return true; };
//(4) dep_a/index.d.ts;
import * as framework from "framework";
export interface IDepA extends framework.IFramework {
a : boolean
}
export default function a(options: IDepA) : boolean;
//(5) dep_a/package.json
{
name: "dep_a",
dependencies: {
"framework" : "0.0.1"
},
...
typings : "index.d.ts" // < Magic happens here
}
Voor framework
//(6) dep_a/node_modules/framework/index.js
module.exports = true // we need index.js here, but we will only use definition file
//(7) dep_a/node_modules/framework/index.d.ts;
export interface IFramework {
b : number;
}
//(8) dep_a/node_modules/framework/package.json
{
name: "framework"
...
typings : "index.d.ts"
}
Wat ik in dit antwoord niet opneem (voor de duidelijkheid) is een andere compilatiefase, dus je zou de modules (dep_a, framework) eigenlijk met TypeScript kunnen schrijven en ze vervolgens compileren naar index.js voordat je ze gebruikt.
