question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[Typescript] Use selectorFamily with an interface

See original GitHub issue

I have a simple interface called Filters

export interface Filters {
  search: string;
}

And I’m trying to use it like with selectorFamily like that: selectorFamily<Patient[], Filters> I’m getting typescript error

Type ‘Filters’ does not satisfy the constraint ‘SerializableParam’. Type ‘Filters’ is not assignable to type ‘Readonly<{ [key: string]: SerializableParam; }>’. Index signature is missing in type ‘Filters’.ts(2344)

If I simply extract the interface selectorFamily<Patient[], { search: string }> it works, but I would happy to not do it

Issue Analytics

  • State:open
  • Created 3 years ago
  • Reactions:6
  • Comments:6 (1 by maintainers)

github_iconTop GitHub Comments

5reactions
sebinsuacommented, Sep 7, 2021

Does this relate to #457, too?

I expanded upon what @Kjaer wrote and have this type in my project:

// The Recoil types for `selectorFamily` have a bug in which they do not
// allow interfaces to be passed in as a parameter.
//
// Therefore, I rewrote the `SelectorMapper` type I found in a comment to handle
// interfaces in deep object hierarchies using TypeScript's conditional types and
// mapped types features.
//
// See: https://github.com/facebookexperimental/Recoil/issues/629#issuecomment-797000984
// See: https://www.typescriptlang.org/docs/handbook/2/mapped-types.html
// See: https://www.typescriptlang.org/docs/handbook/2/conditional-types.html
type CreateSerializableParam<Type> = {
    // We construct a new mapped type in which the keys are the keys of the original type and the values are
    // converted from interface types into normal types (which appears to happen implicitly when using mapped types).
    //
    // When the type of a property is already a `SerializableParam` we return it as-is.
    // But if it is not, we should check to see if it it is a record/object or undefined and then recursively map it.
    // Finally, if it matches neither of these conditions we should return it as-is.
    [Property in keyof Type]: Type[Property] extends import('recoil').SerializableParam
        ? Type[Property]
        : Type[Property] extends Record<string, any> | undefined | null
        ? CreateSerializableParam<Type[Property]>
        : Type[Property];
};

I’m wondering if we should move a fix upstream somehow.

A demonstration of the ‘bug’ can be found here. But I’ve not been able to find a library-level fix for this when Googling…

2reactions
Kjaercommented, Mar 11, 2021

I am dealing with this issue with using Mapped Types(https://www.typescriptlang.org/docs/handbook/2/mapped-types.html)

let’s say I’ve got this interface

interface PaginationArgs {
  limit: number;
  offset: number;
  sort: Array<string>;
}

And I’ve got a selectorFamily as follows:

export const getData = selectorFamily<Array<Data>, PaginationArgs>({
  key: 'getAvailableData',
  get(paginationParams) {
    return async () => {
      const rawData = await someService.fetchData(paginationParams);
      const data = await rawData.json();

      return fetchedNotes;
    };
  },
});

Typescript will throw this error:

TS2344: Type 'PaginationArgs' does not satisfy the constraint 'SerializableParam'.   Type 'PaginationArgs' is not assignable to type 'Readonly<{ [key: string]: SerializableParam; }>'.     Index signature is missing in type 'PaginationArgs'.

and I added this generic type mapper:


type SelectorMapper<Type> = {
  [Property in keyof Type]: Type[Property];
};

export const getData = selectorFamily<Array<Data>, SelectorMapper<PaginationArgs>>({
  key: 'getAvailableData',
  get(paginationParams) {
    return async () => {
      const rawData = await someService.fetchData(paginationParams);
      const data = await rawData.json();

      return fetchedNotes;
    };
  },
});

Typescript will happy now. Hope this will help you all…

Read more comments on GitHub >

github_iconTop Results From Across the Web

selectorFamily(options) - Recoil
A selectorFamily is a powerful pattern that is similar to a selector , but allows you to pass parameters to the get and...
Read more >
TypeScript recoil cheat sheet - SaltyCrane
This is a list of TypeScript types for recoil generated from the declaration files ... P extends SerializableParam> (interface); AtomOptions<T> (interface) ...
Read more >
Recoil with React and TypeScript - DEV Community ‍ ‍
Recoil is yet another state management library for React, I just wanted to give it a try so I decided to re-create my...
Read more >
Integrate Recoil with TypeScript to share your state across ...
In Recoil, we can then use the selector or a selectorFamily . A selectorFamily is a pattern similar to a selector , but...
Read more >
Type interface for selectors constant - Stack Overflow
header__toggle-mode'), rotateBtnStr: '.content__topic-item-btn', },. }; typescript · types · interface.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found