Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does this error say? Type 'ParsedQs' is not assignable to type 'string'

Hello my problem is I want to use the search query of mongoose. But I want to make a get request using a query. Why is that not possible? I do not understand this error. I am using version 5.10.0 of mongoose. I don't want to do it as a post request and I would not like to use req.body. Can anyone help me?

here my code:

export const searching = (req: Request, res: Response) => {
  Company.find({ $text: { $search: req.query } }).exec((err, docs) => {
    if (docs) {
      res.status(200).json(docs)
    } else {
      console.log(err)
    }
  })
}

my error message:

(property) $search: string
No overload matches this call.
The last overload gave the following error.
Type 'ParsedQs' is not assignable to type 'string'.ts(2769)
like image 556
redlightfilms Avatar asked Dec 28 '25 16:12

redlightfilms


2 Answers

req.query is an object containing request query

So if you send a request to the endpoint like this /?foo=bar&a=123

You can access the query value from

req.query.foo // bar
req.query.a // 123

You are passing query object to the $search, meanwhile you are supposed to pass a string, so it should be

Company.find({ $text: { $search: req.query.yourQueryKey as string } }).exec((err, docs) => {

Better solution is to type your RequestHandler function

import {RequestHandler} from "express";

type Params = {};
type ResBody = {};
type ReqBody = {};
type ReqQuery = {
    query: string;
}

export const searching: RequestHandler<Params, ResBody, ReqBody, ReqQuery> = (req, res) => {
    const query = req.query.query; // string
}

Even better solution: type your RequestHandler function and use a validation library to validate the request query like joi or celebrate

like image 123
Owl Avatar answered Dec 30 '25 04:12

Owl


You are passing req.query to your search and the default Typescript type for req.query is

Request<unknown, unknown, unknown, QueryString.ParsedQs, Record<string, any>>.query: QueryString.ParsedQs 

and if you passed in req.query.searchText the type for that would be

string | QueryString.ParsedQs | string[] | QueryString.ParsedQs[] | undefined

The simple way is already answered here just do

export const searching = (req: Request, res: Response) => { 
const searchText = req.query. searchText as string
  Company.find({ $text: { $search: searchText } }).exec((err, docs) => {
    if (docs) {
      res.status(200).json(docs)
    } else {
      console.log(err)
    }
  })
}

That works but gets sloppy when you have a lot of variables from your query params. In express try out the RequestHandler for your endpoints.

import { RequestHandler } from 'express'

interface QueryTypes {
  searchText: string
  moreSearchText: string
}
export const searching:RequestHandler<unknown, unknown, unknown, QueryTypes > = (req, res) => {
  Company.find({ $text: { $search: req.query } }).exec((err, docs) => {
    if (docs) {
      res.status(200).json(docs)
    } else {
      console.log(err)
    }
  })
}

You can see using the RequestHandler I can pass in a few unknown types and the fourth one I can pass in the query types. I can also remove the Request and Response types to just (req, res) because RequestHandler already types out the handler for us.

You're probably wondering what the 3 previous unknown are and that too in the typescript docs for RequestHandler. Here is the docs.

interface RequestHandler<P = core.ParamsDictionary, ResBody = any, ReqBody = any, ReqQuery = qs.ParsedQs, Locals extends Record<string, any> = Record<string, any>>

Now using RequestHandler. I can type out parameters, body, reqbody or query. Use a combo or skip them using unknown like I did in my example.

This also has the added benefit of giving you type safety so

const test = req.query.test

would highlight a typescript error in vscode for me because 'test' is defined in my QueryTypes interface.

like image 42
Richard Torcato Avatar answered Dec 30 '25 05:12

Richard Torcato