I'm starting a small project that uses TypeScript, Next.js, and Socket.io. I don't understand how to tell TypeScript that I am kind of "merging" these two. For example, here are my files.
/api/socket.ts:
import { NextApiRequest, NextApiResponse } from 'next'
import { Server } from 'socket.io'
const SocketHandler = (req: NextApiRequest, res: NextApiResponse) => {
if (res.socket.server.io) {
console.log('Socket is already running.')
} else {
console.log('Socket is initializing...')
const io = new Server(res.socket.server)
res.socket.server.io = io
io.on('connection', (socket) => {
socket.on('input-change', (msg) => {
socket.broadcast.emit('update-input', msg)
})
})
}
res.end()
}
export default SocketHandler
/components/client.tsx:
import { useEffect, useState } from 'react'
import io from 'socket.io-client'
import type { ChangeEvent } from 'react'
import type { Socket } from 'socket.io-client'
let socket: undefined | Socket
export default function Client() {
const [input, setInput] = useState('')
useEffect(() => {
socketInitializer()
}, [])
const socketInitializer = async () => {
fetch('/api/socket')
socket = io()
socket.on('connect', () => {
console.log('connected')
})
socket.on('update-input', (msg) => {
setInput(msg)
})
}
const onChangeHandler = (e: ChangeEvent<HTMLInputElement>) => {
setInput(e.target.value)
if (socket !== undefined) {
socket.emit('input-change', e.target.value)
}
}
return (
<input
placeholder="Type something"
value={input}
onChange={onChangeHandler}
/>
)
}
And this code is working. But I'm getting all kinds of warnings / errors, like "Property 'server' does not exist on type 'Socket'", "Object is possibly 'null'." (on res itself).
I understand the main issue is TypeScript does not know I am adding .io on the res.socket.server object. But what I don't understand is A) how to tell it that I am adding that .io, B) why res and socket are possibly null, and C) why .server does not exist on res.socket, according to TypeScript.
I just need some direction and possibly higher-level explanation of how to tackle this. I think I need a .d.ts file, or maybe I just a new interface, but I am not really sure how to properly write a new interface without over-riding types that are already in place.
socket = io()wouldn't work for me because i had to change the import for io to:import { io } from 'socket.io-client';