创建一个TypeScript库,并通过带有ES6和TypeScript的Node.js使用它 [英] Create a TypeScript Library and use it from Node.js with ES6 and TypeScript

查看:74
本文介绍了创建一个TypeScript库,并通过带有ES6和TypeScript的Node.js使用它的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个TypeScript库作为私有npm包,可以在Node.js中使用(包括使用具有@types支持和TypeScript的ES6的6.x)).

I want to create a TypeScript library as private npm package which can be used in Node.js (including 6.x) using ES6 with @types support and TypeScript.

该库的目标是从express扩展Request类型并提供其他属性.

The goal of the library is to extend the Request type from express and provide additional properties.

我创建了一个新的Node.js项目并添加了tsconfig.json:

I created a new Node.js project and add this tsconfig.json:

{
  "compilerOptions": {
    "target": "es2015",
    "module": "commonjs",
    "sourceMap": true,
    "declaration": true,
    "outDir": "./dist",
    "strict": true,
    "types": ["mocha"]
  }
}

这些是package.json的相关部分:

{
  "name": "@myscope/my-lib",
  "main": "dist",
  "scripts": {
    "build": "rm -rf ./dist && ./node_modules/.bin/tsc",
    "test": "./node_modules/.bin/mocha test"
  },
  "private": true,
  "dependencies": {
    "joi": "11.4.0"
  },
  "devDependencies":  {
    "mocha": "^5.2.0",
    "express": "^4.16.4",
    "@types/express": "^4.16.1",
    "@types/joi": "^14.3.0",
    "@types/mocha": "^5.2.5",
    "typescript": "^3.2.4"
  }
}

我的文件夹结构是这样的:

My folder structure is this:

- dist
- src
  - http
  - security
- test

我在src/http中创建了一个新的TypeScript文件AuthenticatedRequest.ts:

I created a new TypeScript file AuthenticatedRequest.ts in src/http:

import {Request} from "express";
import {UserReference} from "../security/UserReference";

export interface AuthenticatedRequest extends Request {
  user: UserReference
}

src/security包含UserReference.ts:

import {Claim} from "./Claim";

export interface UserReference {
  claims: Claim[];
}

Claim.ts:

import {IClaim} from "./IClaim";

export class Claim implements IClaim {
  type: string;
  value: string;

  constructor(type: string, value: string) {
    this.type = type;
    this.value = value;
  }
}

IClaim.ts看起来像这样:

export interface IClaim {
  type: string,
  value: string
}

test中,我创建了AuthenticatedRequestTests.js(纯ES6,此处没有用于验证ES6中代码的完成和使用情况的TypeScript):

In test, I created AuthenticatedRequestTests.js (plain ES6, no TypeScript here to validation code completion and usage from ES6):

'use strict';

const assert = require('assert');
const Claim = require("../dist/security/Claim").Claim;

describe('req', () => {
  it('should ', done => {
    /** @type {AuthenticatedRequest} */
    const req = {};
    req.user = { claims: [new Claim('tenantId', '123')] };
    assert.equal(req.user.claims[ 0 ].type, 'tenantId');
    assert.equal(req.user.claims[ 0 ].value, '123');
    return done();
  });
});

现在我有一些疑问:

  • 这是解决该问题的预期TypeScript方法吗?
  • 是否可以仅使用require("../dist/security/Claim");代替require("../dist/security/Claim").Claim;?
  • 我想使用/** @type {myLib.http.AuthenticatedRequest} */
  • ,而不是使用此jsdoc语句/** @type {AuthenticatedRequest} */
  • Is this the expected TypeScript way to solve this?
  • Is it possible to just use require("../dist/security/Claim"); instead of require("../dist/security/Claim").Claim;?
  • Instead of using this jsdoc statement /** @type {AuthenticatedRequest} */ I would like to use /** @type {myLib.http.AuthenticatedRequest} */

我还创建了一个用于集成的本地测试项目,并通过npm link安装了我的库.

I also created a local test project for integration and installed my library via npm link.

但是不要使用

const Claim = require("@scope/my-lib/security/Claim").Claim;我必须使用

const Claim = require("@scope/my-lib/dist/security/Claim").Claim;

如何在这里摆脱dist文件夹名称?

How can I get rid of the dist folder name here?

此外,在集成测试项目中对AuthenticatedRequest使用jsdoc注释,我得到一个错误,即找不到类型:

Also, using the jsdoc comment for AuthenticatedRequest in the integration test project, I get the error that the type cannot be found:

推荐答案

package.json

package.json

  • 应该有一个名为types(或typings)的字段,该字段告诉您的库使用者项目的类型定义在哪里.如果它们是由TypeScript生成并保存到dist/index.d.ts,则应使用该路径.

  • There should be a field called types (or typings) telling your library consumers where are the type definitions for your project. If they are generated by TypeScript and saved to dist/index.d.ts, then that's the path that should be used.

"types": "./dist/index.d.ts"

应该有一个名为files的字段,其中包含将交付给最终用户的文件/目录数组.

There should be a field called files containing an array of files/directories that will be delivered to your end users.

运行测试

这是解决该问题的预期TypeScript方法吗?

Is this the expected TypeScript way to solve this?

如果您使用TypeScript开发库,则没有理由不使用TypeScript进行测试.有一些符合TypeScript的测试运行程序(ts-jest曾经很流行,现在Jest能够开箱即用地理解TypeScript.)

If you're using TypeScript to develop your library, there is no reason not to use TypeScript for your tests. There are TypeScript-compliant test runners out there (ts-jest used to be popular, and now Jest is capable of understanding TypeScript out of the box).

是否可以仅使用require("../dist/security/Claim");代替require("../dist/security/Claim").Claim;?

使用TypeScript,可以使用几种语法.您可以使用默认导出导出Claim并执行以下操作:

With TypeScript, a few kinds of syntax are possible. You could export Claim using a default export and do:

import Claim from "../dist/security/Claim";

或:

const Claim = require("../dist/security/Claim");

  • 我不想使用此jsdoc语句/** @type {AuthenticatedRequest} */,而是要使用/** @type {myLib.http.AuthenticatedRequest} */.

    您将需要一个导入类型.它们看起来像这样:

    You will need an import type. They look like that:

    /**
     * @type {import('path/to/AuthenticatedRequest')}
     */
    const req {}
    

    路径可以是相对的或绝对的.如果您希望将本地代码库视为从npm安装的本地代码库,则可以在测试目录中创建另一个package.json文件,并使用相对路径来解析您的库模块.

    The path can be relative or absolute. If you'd like to treat the local codebase as if it were installed from npm, you can create another package.json file in your test directory and use a relative path to resolve your library module.

    "dependencies": {
      "my-library": "../path/to/the/root"
    }
    

  • 此外,在集成测试项目中使用AuthenticatedRequest的jsdoc注释,我得到一个错误,即找不到类型:

    Also, using the jsdoc comment for AuthenticatedRequest in the integration test project, I get the error that the type cannot be found:

    这也可以通过导入类型解决.除非类型不在全局范围内,否则需要先导入它,然后才能使用它.请使用import('path/to/AuthenticatedRequest').

    That's also solved by import types. Unless a type is not in the global scope, you need to import it before you can use it. Use import('path/to/AuthenticatedRequest') instead.

    发生了一些事情.如果您可以创建一个公共存储库来演示您的问题,我相信我们可以更轻松地帮助您解决问题.

    There are a few things going on. If you could create a public repository to demonstrate your problems, I'm sure it would be easier for us to help you address them.

    这篇关于创建一个TypeScript库,并通过带有ES6和TypeScript的Node.js使用它的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆