如何扩展 TypeScript 的类型声明?

Posted

技术标签:

【中文标题】如何扩展 TypeScript 的类型声明?【英文标题】:How to extend type declaration for TypeScript? 【发布时间】:2021-05-03 10:45:12 【问题描述】:

以下问题类似于: Extend Express Request object using Typescript

我几乎尝试了答案和 cmets 中列出的所有组合,但均未成功。由于那个已经超过 4 岁了,我想再次向社区提问:

在 Express 应用程序中,我将 user 属性附加到中间件 auth 中的请求对象。

// index.ts
import express,  Request, Response  from 'express'
.
.
app.get('/test', auth, (req: Request, res: Response) => 
    res.send(welcomeScreen(req.user?.client_name || ''))
)

我收到一个错误:

Property 'user' does not exist on type 'Request<ParamsDictionary, any, any, ParsedQs>'

这是意料之中的。因此,我想扩展 express.Request 对象的类型定义以接受我的 user 属性,假设在自定义 d.ts 文件中。 但无论我如何尝试去做,我仍然得到同样的错误。 d.ts 文件的内容到底应该是什么?到目前为止,我最好的镜头是:

// custom.d.ts
namespace Express 
    export interface Request 
        user?: 
    

添加后,user 属性在 IDE 中被识别:

(property) Express.Request.user?:  | undefined

但我仍然得到相同的编译时错误。 我还需要更改tsconfig 吗?谢谢!

// tsconfig.json

    "compilerOptions": 
        "target": "es6",
        "module": "commonjs",
        "outDir": "./compiled",
        "rootDir": "./src",
        "strict": true,
        "moduleResolution": "node",
        "typeRoots": ["./types"],
        "esModuleInterop": true,       "skipLibCheck": true,
        "forceConsistentCasingInFileNames": true
    

【问题讨论】:

这能回答你的问题吗? Extend Express Request object using Typescript 可以分享一下ts配置文件吗? “但我仍然遇到同样的运行时错误。”你的意思是编译时错误?并尝试不指定 typeRoots - 只需将其包含在 tsconfig.json 的“包含”的全局中? 我更正了这个问题,谢谢。这就是你的意思?"include": ["./types"],好像不行 "include": "src" 文件夹,或者如果您的 index.ts 只是在项目根目录中,则将其完全关闭?我认为您不必为此指定 typeRoots 【参考方案1】:

这是一个棘手的问题,因为有很多变化会产生相似的结果,但我认为这是正确的答案:

添加@types/express-serve-static-core,然后在 express-more.d.ts 文件中:

import  Express  from "express-serve-static-core";

declare global 
    namespace Express 
        interface Request 
            user?: 
        
    


【讨论】:

谢谢杰森,很遗憾我没有工作。也许原因在其他地方,不在 d.ts 文件中? 你的 index.ts 中有import Request from "express"; 没错。我更新了描述。【参考方案2】:

以下是适用于我们团队的解决方案:

// tsconfig.json

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

// @types/express/index.d.ts
export  

declare global 
    namespace Express 
        interface Request 
            user?: 
        
    

最终按预期使用:

// src/index.ts
import express,  Request, Response  from 'express'
...
app.get('/test', auth, (req: Request, res: Response) => 
    res.send(welcomeScreen(req.user))
)

【讨论】:

以上是关于如何扩展 TypeScript 的类型声明?的主要内容,如果未能解决你的问题,请参考以下文章

LayaBox---TypeScript---声明合并

如何在打字稿中正确导入自定义类型

在扩展 EventEmitter 的 TypeScript 类中声明事件

TypeScript:如何声明记录或记录数组的类型?

Typescript:如何声明一种值等于对象键的数组类型?

如何在 TypeScript 中正确要求和声明节点库类型?