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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/39040108/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 07:17:41  来源:igfitidea点击:

Import class in definition file (*d.ts)

typescripttypescript-typings

提问by Micha? Lytek

I want to extend Express Session typings to allow use my custom data in session storage. I have an object req.session.userwhich is an instance of my class User:

我想扩展 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) : "";
    }
}

So i created my own.d.tsfile to merge definition with existing express session typings:

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

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

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

But it's not working at all - VS Code and tsc don't see it. So I created test definition with simple type:

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

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

And the test field is working ok, so the import cause problem.

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

I also tried to add /// <reference path='models/user.ts'/>instead import but the tsc didn't see the User class - how can I use my own class in *d.ts file?

我也尝试添加/// <reference path='models/user.ts'/>而不是导入,但 tsc 没有看到 User 类 - 我如何在 *d.ts 文件中使用我自己的类?

EDIT:I set tsc to generate definition files on compile and now I have my user.d.ts:

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

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

And the own typing file for extending Express Sesion:

以及用于扩展 Express Session 的自己的输入文件:

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

But still not working when import statement on top. Any ideas?

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

回答by Micha? Lytek

After two years of TypeScript development, I've finally managed to solve this problem.

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

Basically, TypeScript has two kind of module types declaration: "local" (normal modules) and ambient (global). The second kind allows to write global modules declaration that are merged with existing modules declaration. What are the differences between this files?

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

d.tsfiles are treated as an ambient module declarations only if they don't have any imports. If you provide an import line, it's now treated as a normal module file, not the global one, so augmenting modules definitions doesn't work.

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

So that's why all the solutions we discussed here don't work. But fortunately, since TS 2.9 we are able to import types into global modules declaration using import()syntax:

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

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

So the line import("./user").User;does the magic and now everything works :)

所以这条线import("./user").User;发挥了神奇的作用,现在一切正常:)

回答by Pelle Jacobs

UPDATE

更新

Since typescript 2.9, you seem to be able to import types into global modules. See the accepted answer for more information.

从 typescript 2.9 开始,您似乎可以将类型导入到全局模块中。有关更多信息,请参阅已接受的答案。

ORIGINAL ANSWER

原答案

I think the problem you're facing is more about augmenting module declarationsthen class typing.

我认为您面临的问题更多是关于增加模块声明然后是类输入。

The exporting is fine, as you'll notice if you try to compile this:

导出很好,如果您尝试编译它,您会注意到:

// app.ts  
import { User } from '../models/user'
let theUser = new User('theLogin', 'thePassword')

It seems like you are trying to augment the module declaration of Express, and you are really close. This should do the trick:

似乎您正在尝试增加 的模块声明Express,并且您真的很接近。这应该可以解决问题:

// index.d.ts
import { User } from "./models/user";
declare module 'express' {
  interface Session {
    user: User;
    uuid: string;
  }
}

However, the correctness of this code depends of course on the original implementation of the express declaration file.

但是,这段代码的正确性当然取决于 express 声明文件的原始实现。

回答by masa

Is it not possible just to follow the logic with express-session:

难道不能只遵循以下逻辑express-session

own.d.ts:

own.d.ts

import express = require('express');
import { User } from "../models/user";

declare global {
    namespace Express {
        interface Session {
            user: User;
            uuid: string;
        }
    }
}

In the main index.ts:

在主要index.ts

import express from 'express';
import session from 'express-session';
import own from './types/own';

const app = express();
app.get('/', (req, res) => {
    let username = req!.session!.user.login;
});

At least this seems to compile without any issues. For the full code, see https://github.com/masa67/so39040108

至少这似乎编译没有任何问题。完整代码见https://github.com/masa67/so39040108