Je souhaite étendre les typages de session express pour permettre l'utilisation de mes données personnalisées dans le stockage de session. J'ai un objet req.session.user
qui est une instance de ma classe User
:
export class User {
public login: string;
public hashedPassword: string;
constructor(login?: string, password?: string) {
this.login = login || "" ;
this.hashedPassword = password ? UserHelper.hashPassword(password) : "";
}
}
J'ai donc créé mon own.d.ts
fichier pour fusionner la définition avec les types de session express existants:
import { User } from "./models/user";
declare module Express {
export interface Session {
user: User;
}
}
Mais cela ne fonctionne pas du tout - VS Code et tsc ne le voient pas. J'ai donc créé une définition de test avec un type simple:
declare module Express {
export interface Session {
test: string;
}
}
Et le champ de test fonctionne correctement, donc le problème de cause d'importation.
J'ai également essayé d'ajouter /// <reference path='models/user.ts'/>
au lieu d'importer mais le tsc n'a pas vu la classe User - comment puis-je utiliser ma propre classe dans le fichier * d.ts?
EDIT: J'ai défini tsc pour générer des fichiers de définition lors de la compilation et maintenant j'ai mon user.d.ts:
export declare class User {
login: string;
hashedPassword: string;
constructor();
constructor(login: string, password: string);
}
Et le propre fichier de saisie pour étendre Express Sesion:
import { User } from "./models/user";
declare module Express {
export interface Session {
user: User;
uuid: string;
}
}
Mais ne fonctionne toujours pas lorsque la déclaration d'importation est en haut. Des idées?
Après deux ans de développement TypeScript, j'ai finalement réussi à résoudre ce problème.
Fondamentalement, TypeScript a deux types de déclaration de types de module: "local" (modules normaux) et ambiant (global). Le deuxième type permet d'écrire une déclaration de modules globale qui est fusionnée avec la déclaration de modules existante. Quelles sont les différences entre ces fichiers?
Les fichiers d.ts
Sont traités comme des déclarations de module ambiant uniquement s'ils n'ont aucune importation. Si vous fournissez une ligne d'importation, elle est désormais traitée comme un fichier de module normal, et non comme un fichier global, donc l'augmentation des définitions de modules ne fonctionne pas.
C'est pourquoi toutes les solutions dont nous avons discuté ici ne fonctionnent pas. Mais heureusement, depuis TS 2.9, nous sommes en mesure d'importer des types dans la déclaration des modules globaux en utilisant la syntaxe import()
:
declare namespace Express {
interface Request {
user: import("./user").User;
}
}
Donc cette ligne import("./user").User;
fait la magie et maintenant tout fonctionne :)
MISE À JOUR
Depuis TypeScript 2.9, vous semblez pouvoir importer des types dans des modules globaux. Voir la réponse acceptée pour plus d'informations.
RÉPONSE ORIGINALE
Je pense que le problème auquel vous êtes confronté concerne davantage augmentant les déclarations du module que le typage de classe.
L'exportation est très bien, comme vous le remarquerez si vous essayez de compiler ceci:
// app.ts
import { User } from '../models/user'
let theUser = new User('theLogin', 'thePassword')
Il semble que vous essayez d'augmenter la déclaration de module de Express
, et vous êtes vraiment proche. Cela devrait faire l'affaire:
// index.d.ts
import { User } from "./models/user";
declare module 'express' {
interface Session {
user: User;
uuid: string;
}
}
Cependant, l'exactitude de ce code dépend bien sûr de l'implémentation d'origine du fichier de déclaration express.
N'est-il pas possible de suivre la logique avec express-session
:
own.d.ts
:
import express = require('express');
import { User } from "../models/user";
declare global {
namespace Express {
interface Session {
user: User;
uuid: string;
}
}
}
En général 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;
});
Au moins, cela semble se compiler sans aucun problème. Pour le code complet, voir https://github.com/masa67/so39040108