简体   繁体   English

在打字稿库中导出扩展快递请求

[英]Export extended express request in typescript library

I'm trying to create a library which extends the express Response with a property warn() and when using the library I want to have the new property warn() available.我正在尝试创建一个库,该库使用属性warn()扩展express Response ,并且在使用该库时,我希望新的属性warn()可用。

This is my tsconfig.json这是我的tsconfig.json

{
  "compilerOptions": {
    "module": "commonjs",
    "esModuleInterop": true,
    "declaration": true,
    "target": "es6",
    "moduleResolution": "node",
    "sourceMap": true,
    "outDir": "dist",
    "baseUrl": ".",
    "paths": {
      "*": ["node_modules/*"]
    },
    "types": ["mocha"],
    "typeRoots": ["@types"]
  },
  "include": ["src/**/*", "test/**/*"]
}

This is my @types/express/index.d.ts :这是我的@types/express/index.d.ts

import * as express from 'express'
import http from 'http'

export {}

declare global {
  namespace Express {
    export interface Response<ResBody = any>
      extends http.ServerResponse,
        express.Response {
      warn(): this
    }
  }
}

src/registerwarn.ts : src/registerwarn.ts

export function registerwarn() {
  return (_req: Request, res: Express.Response, next): void => {
    res.warn = (): Express.Response => {
      console.log("warning");
      return res;
    };
    return next();
  };
}

src/warnings.ts : src/warnings.ts

import { registerwarn } from './registerwarn'
export default [registerwarn()]

A test:一个测试:

test/warningtest.ts : test/warningtest.ts

import 'should'
import express, { Request, Response } from 'express'
import warnings from '../src/warnings'

describe('test', (): void => {
  const app = express()
  app.use(warnings)
  app.get('/', (req: Request, res: Response) => {
    res.status(200).warn().send({ some: 'content' })
  })
  it('should ', (done) => {
    done()
  })
})

Running tsc returns these errors:运行tsc返回以下错误:

src/registerwarn.ts:3:9 - error TS2339: Property 'warn' does not exist on type 'Response'.

     res.warn = (): Express.Response => {
         ~~~~

test/hello_tests.ts:9:21 - error TS2339: Property 'warn' does not exist on type 'Response<any>'.

     res.status(200).warn().send({ some: 'content' })
                     ~~~~


Found 2 errors.

error Command failed with exit code 2.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

How can I get rid of these errors and make sure if somebody uses the library from npm doesn't get these warnings as well?我怎样才能摆脱这些错误,并确保是否有人使用npm中的库也没有收到这些警告?

I created a repro here .我在这里创建了一个复制品。

There are two possible solutions here I have identified, although I am unable to comment whether this is the "best" solution available - these are merely what I came up with.我在这里确定了两种可能的解决方案,尽管我无法评论这是否是可用的“最佳”解决方案 - 这些只是我想出的。

Solution I (recommended): Remove mocha from globally declared types in tsconfig.json解决方案 I(推荐):从tsconfig.json全局声明的types中删除mocha

As per the documentation on tsconfig.json 's compilerOptions.types , declaring mocha under types will significantly restrict the visibility of @types packages.由于每对文档tsconfig.jsoncompilerOptions.types ,宣告mochatypes将显著限制的知名度@types包。

By default all visible ”@types” packages are included in your compilation.默认情况下,所有可见的“@types”包都包含在您的编译中。 Packages in node_modules/@types of any enclosing folder are considered visible.任何封闭文件夹的 node_modules/@types 中的包都被认为是可见的。 For example, that means packages within ./node_modules/@types/, ../node_modules/@types/, ../../node_modules/@types/, and so on.例如,这意味着 ./node_modules/@types/、../node_modules/@types/、../../node_modules/@types/ 等中的包。
If types is specified, only packages listed will be included in the global scope.如果指定了类型,则仅列出的包将包含在全局范围内。 For instance:例如:

 { "compilerOptions": { "types": ["node", "jest", "express"] } }

This tsconfig.json file will only include ./node_modules/@types/node, ./node_modules/@types/jest and ./node_modules/@types/express.此 tsconfig.json 文件将仅包含 ./node_modules/@types/node、./node_modules/@types/jest 和 ./node_modules/@types/express。 Other packages under node_modules/@types/* will not be included. node_modules/@types/* 下的其他包将不包含在内。

By dropping the compilerOptions.types flag altogether, your typing should now be visible.通过完全删除compilerOptions.types标志,您的输入现在应该是可见的。

Within your test file, you should now add an import line for import 'mocha' to gain access to testing methods (eg describe , it , etc).在您的测试文件中,您现在应该为import 'mocha'添加一个导入行以访问测试方法(例如describeit等)。 This will need to be done for each test.每次测试都需要这样做。 I would recommend using an import, as it is a bit clearer where your declarations are coming from (and not invisibly popping up as a result of your tsconfig.json ).我建议使用导入,因为它更清楚你的声明来自哪里(并且不会因为你的tsconfig.json不可见地弹出)。

Additionally, I am not sure that you would want mocha to be declared globally here either, as mocha test imports would automatically be visible under files in the src folder.另外,我不知道,你想mocha在全球范围内无论是在这里声明,如mocha测试进口将自动成为下的文件可见src文件夹。 I suspect you might run into some other strange errors using this flag.我怀疑您使用此标志可能会遇到其他一些奇怪的错误。

Note: I suppose you could alternative double-down with the types flag and add "express" to this list, which will locate your module augmentation under @types .注意:我想您可以使用types标志替代加倍并将"express"添加到此列表中,这将在@types下找到您的模块扩充。 Your mileage may vary significantly with this flag.您的里程可能会因此标志而有很大差异。

Solution II: Explicitly add your @types .d.ts declarations under the include field.解决方案二:在include字段下显式添加@types .d.ts声明。

By specifying the compilerOptions.types flag, visibility is now removed from your custom @types directory.通过指定compilerOptions.types标志,现在可以从您的自定义@types目录中删除可见性。 You can hack this back in by modifying the include flag from您可以通过修改include标志

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

to

"include": ["src/**/*", "test/**/*", "@types/**/*.d.ts"]

I am not too keen on this solution, as it does not address the underlying cause of @types not being visible.我不太喜欢这个解决方案,因为它没有解决@types不可见的根本原因。 You may experience strange errors with this route.您可能会遇到此路线的奇怪错误。


After choosing a solution above (or possibly finding an alternative solution), you need to resolve a few typing errors in the project:在选择上述解决方案(或可能找到替代解决方案)后,您需要解决项目中的一些打字错误:

  • The typings for your warnings sources does not seem to be compatible with any app.use overload.您的警告源的类型似乎与任何app.use重载不兼容。 tests/hello_tests.ts is complaining about no matching type overload for app.use(warnings) . tests/hello_tests.ts抱怨app.use(warnings)没有匹配的类型重载。
  • You do not need to specify any extends for your Response interface - all interfaces under the same namespace will be merged.您不需要为您的Response接口指定任何extends - 将合并同一名称空间下的所有接口。 Since you are declaring an extends on express.Response , the same interface you are augmenting and merging, the interface declaration is now recursively referencing itself and causing an error: Type 'Response<ResBody>' recursively references itself as a base type.由于您在express.Response上声明了一个 extends ,即您正在扩充和合并的同一接口,接口声明现在递归地引用自身并导致错误: Type 'Response<ResBody>' recursively references itself as a base type. . . Dropping this extends clause resolves this error and preserves the functionality you desire.删除此extends子句可解决此错误并保留您想要的功能。
     declare global { namespace Express { export interface Response<ResBody = any> { warn(): this } } }

    Note that I preserved the generic in this instance, but it is optional.请注意,我在本例中保留了泛型,但它是可选的。 If any of your new functionalities require the generic, you should specify it (as demonstrated above).如果您的任何新功能需要泛型,您应该指定它(如上所示)。

After these typing issues are resolved, tsc exits successfully and reports no errors.解决这些键入问题后, tsc成功退出并且不报告任何错误。


As an aside that is unrelated to your question, your prettier configuration is having a field day with CRLF / \\r\\n line endings (ie an error on every line).顺便说一句,与您的问题无关,您prettier配置有一个带有CRLF / \\r\\n行结尾的字段日(即每一行都有错误)。 You should configure your configuration to be more relaxed , or specify a .gitattributes file in your Git repository so that line endings are LF / \\n (and not CRLF / \\r\\n ) by default on checkout.您应该将配置配置为更宽松,或者在您的 Git 存储库中指定一个.gitattributes文件,以便在结帐时默认情况下行尾是LF / \\n (而不是CRLF / \\r\\n )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM