在定义文件 (\*d.ts) 中导入类

新手上路,请多包涵

我想扩展 Express Session 类型以允许在会话存储中使用我的自定义数据。我有一个对象 req.session.user 这是我的类的一个实例 User

 export class User {
    public login: string;
    public hashedPassword: string;

    constructor(login?: string, password?: string) {
        this.login = login || "" ;
        this.hashedPassword = password ? UserHelper.hashPassword(password) : "";
    }
}

所以我创建了我的 own.d.ts 文件以将定义与现有的快速会话类型合并:

 import { User } from "./models/user";

declare module Express {
    export interface Session {
        user: User;
    }
}

但它根本不起作用 - VS Code 和 tsc 看不到它。所以我用简单的类型创建了测试定义:

 declare module Express {
    export interface Session {
        test: string;
    }
}

并且测试字段工作正常,因此导入导致问题。

我还尝试添加 /// <reference path='models/user.ts'/> 代替 import 但 tsc 没有看到 User 类 - 我如何在 *d.ts 文件中使用我自己的类?

编辑: 我将 tsc 设置为在编译时生成定义文件,现在我有了 user.d.ts:

 export declare class User {
    login: string;
    hashedPassword: string;
    constructor();
    constructor(login: string, password: string);
}

以及用于扩展 Express Session 的自己的打字文件:

 import { User } from "./models/user";
declare module Express {
    export interface Session {
        user: User;
        uuid: string;
    }
}

但是当 import 声明在上面时仍然不起作用。有任何想法吗?

原文由 Michał Lytek 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 633
2 个回答

经过两年的 TypeScript 开发,我终于设法解决了这个问题。

基本上,TypeScript 有两种模块类型声明:“本地”(普通模块)和环境(全局)。第二种允许编写与现有模块声明合并的全局模块声明。这些文件有什么区别?

d.ts 文件仅在没有任何导入时才被视为环境模块声明。如果您提供导入行,它现在被视为普通模块文件,而不是全局文件,因此扩充模块定义不起作用。

这就是为什么我们在这里讨论的所有解决方案都不起作用的原因。但幸运的是,从 TS 2.9 开始,我们可以使用 import() 语法将类型导入全局模块声明:

 declare namespace Express {
  interface Request {
    user: import("./user").User;
  }
}

所以 import("./user").User; 行具有魔力,现在一切正常 :)

原文由 Michał Lytek 发布,翻译遵循 CC BY-SA 4.0 许可协议

请看这里:

https://stackoverflow.com/a/43688680/5412249

可以在模块中声明类型(即在使用导入/导出的文件中)并将这些类型扩充(合并)到全局命名空间中。

关键是将类型定义放在一个

declare global { ... }

以下是赛普拉斯用户熟悉的示例:

 // begin file: custom_command_login.ts

import { foo } from './utils';

Cypress.Commands.add('logIn', () => {

   // ...

});

// add custom command to Cypress namespace
// so that intellisense will correctly show the new command
// cy.logIn

declare global {
  namespace Cypress {
    interface Chainable {
       logIn();
    }
  }
}

// end file: custom_command_login.ts

原文由 Jobin Jacob Kavalam 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进