Import class in definition file (*d.ts)

后端 未结 4 1000
面向向阳花
面向向阳花 2020-11-28 21:03

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

相关标签:
4条回答
  • 2020-11-28 21:37

    Thanks to the answer from Michał Lytek. Here is another method I used in my project.

    We can import User and reuse it multiple times without write import("./user").User everywhere, and even extend it or re-export it.

    declare namespace Express {
      import("./user");  // Don't delete this line.
      import { User } from "./user";
    
      export interface Request {
        user: User;
        target: User;
        friend: User;
      }
    
      export class SuperUser extends User {
        superPower: string;
      }
    
      export { User as ExpressUser }
    }
    

    Have fun :)

    0 讨论(0)
  • 2020-11-28 21:50

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

    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?

    d.ts files 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.

    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:

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

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

    0 讨论(0)
  • 2020-11-28 21:57

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

    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:

    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

    0 讨论(0)
  • 2020-11-28 22:04

    UPDATE

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

    ORIGINAL ANSWER

    I think the problem you're facing is more about augmenting module declarations then 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:

    // 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.

    0 讨论(0)
提交回复
热议问题