lukemorales / query-key-factory

A library for creating typesafe standardized query keys, useful for cache management in @tanstack/query
https://www.npmjs.com/package/@lukemorales/query-key-factory
MIT License
1.16k stars 32 forks source link

queryKey required with createQueryKeyStore #75

Closed snebjorn closed 1 year ago

snebjorn commented 1 year ago

When using createQueryKeyStore the queryKey is required but it's already set to a sensible value via Standardized keys

export const queries = createQueryKeyStore({
  users: {
    list: () => ({
      queryKey: ['MUST WRITE SOMETHING'], // <------------------------- 👀 
      queryFn: () => [],
    }),
  },
});

Shouldn't queryKey be optional here? Or am I missing something?

lukemorales commented 1 year ago

@snebjorn this is more for type-inference, as allowing it to be optional makes the type inference not as accurate. If you don't need a value for the queryKey, you can just declare it as null

snebjorn commented 1 year ago

@lukemorales null is an acceptable solution. But I'm having trouble getting it to work.

image

Type '() => { queryKey: null; queryFn: () => never[]; }' is not assignable to type 'FactoryProperty | DynamicKey'.
  Type '() => { queryKey: null; queryFn: () => never[]; }' is not assignable to type 'DynamicKey'.
    Type '{ queryKey: null; queryFn: () => never[]; }' is not assignable to type 'KeyTuple | QueryKeyRecord | DynamicQueryFactoryWithContextualQueriesSchema | DynamicQueryFactorySchema | DynamicKeySchemaWithContextualQueries'.
      Type '{ queryKey: null; queryFn: () => never[]; }' is not assignable to type 'DynamicQueryFactorySchema'.
        Type '{ queryKey: null; queryFn: () => never[]; }' is not assignable to type 'QueryKeyRecord'.
          Types of property 'queryKey' are incompatible.
            Type 'null' is not assignable to type 'KeyTuple'.ts(2322)

image

Type '() => { queryKey: [null]; queryFn: () => never[]; }' is not assignable to type 'FactoryProperty | DynamicKey'.
  Type '() => { queryKey: [null]; queryFn: () => never[]; }' is not assignable to type 'DynamicKey'.
    Type '{ queryKey: [null]; queryFn: () => never[]; }' is not assignable to type 'KeyTuple | QueryKeyRecord | DynamicQueryFactoryWithContextualQueriesSchema | DynamicQueryFactorySchema | DynamicKeySchemaWithContextualQueries'.
      Type '{ queryKey: [null]; queryFn: () => never[]; }' is not assignable to type 'DynamicQueryFactorySchema'.
        Type '{ queryKey: [null]; queryFn: () => never[]; }' is not assignable to type 'QueryKeyRecord'.
          Types of property 'queryKey' are incompatible.
            Type '[null]' is not assignable to type 'KeyTuple'.
              Type '[null]' is not assignable to type '[ValidValue, ...(ValidValue | undefined)[]]'.
                Type at position 0 in source is not compatible with type at position 0 in target.
                  Type 'null' is not assignable to type 'ValidValue'.ts(2322)
lukemorales commented 1 year ago

Oh, I'm sorry @snebjorn I overlooked this detail in your example: if you don't have a dynamic query, you shouldn't initialize the query with a function:

export const queries = createQueryKeyStore({
  users: {
    list: {
      queryKey: null, // `null` works here
      queryFn: () => [],
    },
  },
});

If you initialize the property with a function, then the type-system understands that you're creating a dynamic function and will expect an array in queryKey with the dynamic values you're passing to it:

export const queries = createQueryKeyStore({
  users: {
    list: (page: string) => ({
      queryKey: [page]
      queryFn: () => [],
    }),
  },
});
snebjorn commented 1 year ago

Ah I see. Thanks for the help :)