visual studio code - La fusión de la declaración de interfaz de TypeScript para Socket.IO no funciona
He estado dando vueltas buscando cómo agregar una propiedad a una interfaz para Socket.IO v3. Así que, naturalmente, he mirado en la documentación de TypeScript sobre la ampliación de módulos y cómo escribir archivos de declaración, pero no puedo hacerlo funcionar, y no sé qué estoy haciendo mal. Entonces, lo que sucede es que VSCode se queja de que la propiedad session no existe en la interfaz Handshake.
Esto es lo que estoy intentando lograr:
// src/types/socket.io/index.d.ts
import { Session, SessionData } from "express-session";
import { EntityContext } from "../../contexts/EntityContext";
declare module "socket.io" {
interface Handshake {
session?: Session & Partial<SessionData>;
sessionID?: string;
context?: EntityContext;
}
}
Estructura del Proyecto
- package.json
- tsconfig.json
- /src
- /types
- /socket.io
- index.d.ts
- index.ts
// tsconfig.json
{
"compilerOptions": {
"lib": [
"es5",
"es6"
],
"target": "es5",
"module": "commonjs",
"moduleResolution": "node",
"outDir": "./build",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"sourceMap": true,
"allowSyntheticDefaultImports": true,
"baseUrl": ".",
"typeRoots": [
"node_modules/@types",
"src/types"
],
"paths": {
"socket.io": ["node_modules/socket.io/dist", "src/types/socket.io"]
}
},
"files": [
"src/index.ts",
"src/types/socket.io/index.d.ts"
]
}
// package.json
{
...
"dependencies": {
"apollo-server-express": "^2.21.1",
"argon2": "^0.27.1",
"connect-redis": "^5.1.0",
"cors": "^2.8.5",
"dataloader": "^2.0.0",
"express": "^4.17.1",
"express-session": "^1.17.1",
"graphql": "^15.5.0",
"pg": "^8.5.1",
"redis": "^3.0.2",
"reflect-metadata": "^0.1.10",
"socket.io": "^3.1.2",
"type-graphql": "^1.1.1",
"typeorm": "0.2.31",
"express-socket.io-session": "^1.3.5"
},
"devDependencies": {
"@types/component-emitter": "^1.2.10",
"@types/connect-redis": "0.0.16",
"@types/cookie": "^0.4.0",
"@types/cors": "^2.8.10",
"@types/express": "^4.17.11",
"@types/express-session": "^1.17.3",
"@types/node": "^8.0.29",
"@types/redis": "^2.8.28",
"ts-node": "3.3.0",
"typescript": "3.3.3333"
}
}
No sé si puedes darte cuenta, pero prácticamente he cogido todo lo que he encontrado para intentar resolver esto, pero sin éxito. Simplemente no entiendo cómo deberían funcionar las declaraciones..
Si alguien puede detectar cualquier error que haya cometido o si pueden indicarme una guía que pueda resolver esto para TypeScript 3 y VSCode, lo agradecería mucho.
Déjame saber si necesitas más información y te la proporcionaré.
Respuesta #1
Tu declaración de módulo se llama 'socket.io', porque mapeaste los tipos en el tsconfig, pero esto no es necesario. También mapeaste el archivo de tipos en sí "socket.io": ["node_modules/socket.io/dist", "src/types/socket.io"], lo que probablemente rompe la ampliación. Además, node_modules/socket.io/dist es la ruta incorrecta. La ruta correcta sería node_modules/socket.io/dist/socket. Recomendaría eliminar toda la configuración de path, ya que solo complicará las cosas.
Sin la configuración de rutas, tienes que indicarle a TypeScript exactamente qué módulo quieres aumentar, como se muestra en los ejemplos de la documentación. Cuando importas la interfaz Handshake sin aumentar, normalmente proviene de 'socket.io/dist/socket'. Así que la ruta que usarías para una importación normal, como import { Handshake } from 'socket.io/dist/socket';, también es el nombre del módulo declarado. También tienes que agregar una importación para la interfaz original Handshake, si quieres fusionar las declaraciones y no reemplazarla. El archivo *.d.ts debería verse así:
import { Session, SessionData } from "express-session";
import { EntityContext } from "../../contexts/EntityContext";
// You need to import the original interface to extend it, if you don't,
// you will instead replace the orginal Handshake interface with your own definition.
import { Handshake } from 'socket.io/dist/socket';
declare module 'socket.io/dist/socket' {
interface Handshake {
session?: Session & Partial<SessionData>;
sessionID?: string;
context?: EntityContext;
}
}
