2

I am migrating a Nodejs project to TypeScript. Starting from index.js, changed it to index.ts and did the necessary change for ts. But now I hit the error

src/index.ts:34:90 - error TS2300: Duplicate identifier 'string'.

34   socket.on('login', async function ({ user_id:string}) {...}

I have tried most of answers in Confusing "duplicate identifier" Typescript error message but they all failed to work for me, which includes:

  1. npm install @types/node --save-dev and add "typeRoots": ["node_modules/@types"]
  2. re-install node_modules folder
  3. mess with compilerOptions

This is my tsconfig.json

{
  "compilerOptions": {
    "target": "es2016",
    "module": "commonjs",
    // "typeRoots": ["node_modules/@types"], /* turn it on/off makes no difference */
    "allowJs": true,
    "sourceMap": true,
    "outDir": "./build",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true 
    // "skipDefaultLibCheck": true, /* turn it on/off makes no difference */            
    "skipLibCheck": true   
  },
  "files": ["src/index.ts"], /*I only want to tsc this file*/
  "exclude": ["node_modules"]
}

I did not install @types/express but according to https://github.com/Microsoft/TypeScript/issues/247, "If a module doesn't have type data available (via a .d.ts file), the ES6 module syntax,one must use the CommonJS alternative". It seems to work, so I mix require with import in my codes.

Could this be the reason ?

import { Server, Socket } from "socket.io";

var express = require('express')
var app = express()
var cors = require('cors')
var http = require('http').Server(app)

--- update ---

Except for the answer @Jared Smith gave, I find Typed function parameters using destructuring and rest in TypeScript provide more detailed information.

1
  • That syntax doesn't mean what you think it does. You probably want ({user_id}: {user_id:string} ) Commented Nov 25, 2021 at 11:38

1 Answer 1

2

You can't just add type annotations in function parameter destructuring like that. Change your code to this:

socket.on('login', async function ({ user_id }: { user_id:string }) {...}

Here in the signature for the callback we have the regular destructuring part { user_id } but the parameter to that function is still an object with a user_id property and needs to be typed as such. I'll re-write it below with the type extracted and the parameter non-destructured to maybe help give the idea:

type User = {
  user_id: string
}

socket.on('login', async function (user: User) {
   const user_id = user.user_id;
   // do something
})

This is equivalent to the above inlined version and there isn't a syntactic shortcut.

Sign up to request clarification or add additional context in comments.

2 Comments

Say my day! One more question, if I use type User = {...} then I can't do parameter destructuring, right ?
@Qiulang邱朗 no you totally can: async function ({ user_id }: User) {...} I just spelled it all out to show the correct order of the syntax.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.