redis / node-redis

Redis Node.js client
https://redis.js.org/
MIT License
16.86k stars 1.87k forks source link

Create Redis client in TypeScript. Reis 4.0.0. #1748

Closed DimitriiKr closed 2 years ago

DimitriiKr commented 2 years ago

Hi all, I am relative new to TypeScritp. That's why my question is eventually really obvious. I need help with creating a redis client in TypeScript. Especially declaring a client type:

let redisClient:  RedisClientType | undefined

  export async function useRedis(): RedisClientType {
      if (!redisClient){
          redisClient = createClient( { /* redis options */} )
          await redisClient.connect()
      }

      return redisClient
  }

With this code I receive a TypeScript error "type RedisClientType<...> is not assignable to never".

What is the right approach to instantiate redis client? Perhaps you could just provide an TypeScript example.

Thank you in advance

wingedrhino commented 2 years ago

Ahoy! I'd also like inputs on this. What is the type of the object returned by createClient({url})?

jamesarosen commented 2 years ago

What is the type of the object returned by createClient({url})?

It's RedisClientType, which comes from @node-redis/client/dist/lib/client. The only solution I've found is

import { RedisClientType } from '@node-redis/client/dist/lib/client';

but this has two cons:

  1. I have to depend on @node-redis/client directly. It should be an implementation detail of the redis package.
  2. I'm reaching pretty far into the internals of that package.

Together, these two things mean my code is likely to break when these packages change.

jamesarosen commented 2 years ago

1732 has more on this

DimitriiKr commented 2 years ago

thank you @jamesarosen. import { RedisClientType } from '@node-redis/client/dist/lib/client'; Is exactly the import I have. But still, if you specify type of the variable for the client, TypeScript shows a Type Error:

let redisClient : RedisClientType = createClient( {options} ) 

//=> redisClient has following error:
// Error:(12, 9) TS2322: Type 'RedisClientType<{ json: { ARRAPPEND: typeof import("C:/workspace/......   Types of property 'options' are incompatible.

So, I still don't know, how to use RedisClientType - how to specify a variable type or return type of a function.

jamesarosen commented 2 years ago

This worked for me:

import { createClient } from 'redis'

export type RedisClientType = ReturnType<typeof createClient>

export default async function start(): Promise<RedisClientType> {
  const redis: RedisClientType = createClient({ url: … })
  await redis.connect()
  return redis
}
DimitriiKr commented 2 years ago

Define and export own redis client type worked for me!

export type RedisClientType = typeof client // OK

The second option to get the redis client type as ReturnType doesn't work for function return types:

export type RedisClientType = ReturnType<typeof createClient> // not working as function return type

export function useRedis() : Promise<RedisClientType>
{
...
return client   // <= Error TS2719:... Two different types with this name exist, but they are unrelated.... The types returned by 'multi()' are incompatible between these types.
}

Working example:

const client = createClient( {options} )
export type RedisClientType = typeof client 

export function useRedis() : Promise<RedisClientType>
{
...
await client.connect()
...
return client
}
leibale commented 2 years ago

Duplicate of #1673

leviermonaites commented 3 months ago

Guys, if you take on the approach suggested by our fellow @jamesarosen you are probably going to hit some performance issues when compiling your typescript project.

I removed this explicit workaroundy type definition and it decreased my build time from 5+ minutes to 5 seconds.

That's what I experienced