Skip to content

Conflicting types in the "Unstorage compatibility" example #14339

Description

@ArmandPhilippot

📚 Subject area/topic

Session Driver API

📋 Page(s) affected (or suggested, for new content)

https://docs.astro.build/en/reference/session-driver-reference/#unstorage-compatibility
https://docs.astro.build/en/guides/sessions/#overriding-the-configuration-at-runtime

📋 Description of content that is out-of-date or incorrect

The last code snippet in Unstorage compatibility triggers TypeScript errors.

  • no type on config
  • on the return statement:
    Type 'Driver<RedisOptions, any>' is not assignable to type 'SessionDriver'.
      Types of property 'removeItem' are incompatible.
        Type '((key: string, opts: TransactionOptions) => MaybePromise<void>) | undefined' is not assignable to type '(key: string) => Promise<void>'.
          Type 'undefined' is not assignable to type '(key: string) => Promise<void>'.
    
  • on tls:
    Object literal may only specify known properties, and 'tls' does not exist in type 'RedisOptions'.
    

The issues on config and ttl are easily fixable. But, the one on return suggests a compatibility issue. And, we can't "fix" that with a cast:

Conversion of type 'Driver<RedisOptions, any>' to type 'SessionDriver' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
  Types of property 'removeItem' are incompatible.
    Type '((key: string, opts: TransactionOptions) => MaybePromise<void>) | undefined' is not comparable to type '(key: string) => Promise<void>'.
      Type '(key: string, opts: TransactionOptions) => MaybePromise<void>' is not comparable to type '(key: string) => Promise<void>'.
        Target signature provides too few arguments. Expected 2 or more, but got 1.

If I try an absurd workaround:

import type { SessionDriver } from "astro";
import redisDriver, { type RedisOptions } from "unstorage/drivers/redis";

export default function (config: RedisOptions): SessionDriver {
  const unstorageDriver = redisDriver({
    ...config,
    ttl: config.ttl ?? 60 * 60 * 24 * 7, // default to 7 days
  });
  return {
    ...unstorageDriver,
    async removeItem(key) {
      if (unstorageDriver.removeItem) {
        return await unstorageDriver.removeItem(key, {});
      }
      return void 0;
    },
  };
}

It seems other APIs are incompatible. I now get:

Type '{ removeItem(key: string): Promise<void>; name?: string | undefined; flags?: DriverFlags | undefined; options?: RedisOptions | undefined; ... 12 more ...; watch?: ((callback: WatchCallback) => MaybePromise<...>) | undefined; }' is not assignable to type 'SessionDriver'.
  The types returned by 'getItem(...)' are incompatible between these types.
    Type 'MaybePromise<StorageValue>' is not assignable to type 'Promise<any>'.
      Type 'null' is not assignable to type 'Promise<any>'.

So:

  • Should we remove the "Alternatively, [...]" part in docs? (or even the whole "Unstorage compatibility" section? I don't know if the first part work on a real project)
  • Should the code snippet be updated in some way?
  • Should this be an issue in core to find a fix?

cc @florian-lefebvre as you authored that page (#12951), maybe you have ideas on this.

🖥️ Reproduction in StackBlitz (if reporting incorrect content or code samples)

https://stackblitz.com/edit/astro-session-unstorage?file=src%2Fdriver%2Fruntime.ts&on=stackblitz

This contains fixes for config (import RedisOptions) and tls (swap with ttl) and only reproduces the return statement error.

You should see the error in Stackblitz. Otherwise, you can run npm run astro check.

Metadata

Metadata

Assignees

No one assigned

    Labels

    code snippet updateUpdates a code sample: typo, outdated code etc.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions