svelte-persistent-store icon indicating copy to clipboard operation
svelte-persistent-store copied to clipboard

Using Custom Type in persist() which accepts any[]

Open michaelcuneo opened this issue 3 years ago • 3 comments
trafficstars

So I've started learning and transitioning to .TS because it appears as though that is a good thing. But I'm having a hard time translating some components and helpers to TS... particularly this svelte-persistent-store.

I have a class Store, with a constructor, with all my publics. ... as follows.

    public projects: Writable<object> = persist(writable([]), localStorage(), 'projects'),
    public humans: Writable<humanType> = persist(writable([]), localStorage(), 'humans'),

I started to write a custom Interface called humanType, to use instead of the default, string/object/number, etc...

interface humanType {
  id: string;
  firstName: string;
  lastName: string;
  title: string;
  name: string;
  mugshot: string;
  messages: {
    items: object[];
  }
  roles: {
    items: object[];
  }
  createdAt: string;
  updatedAt: string;
  website: string;
  email: string;
};

But now that line errors...

Type PersistentStore<any[]> is not assignable to type Writeable<humanType>

Is this a matter of how svelte-persistent-store is written, or how Writable in svelte/store is written, or a combination of the two... I'm not familiar enough with .TS to figure out what I've done here.

michaelcuneo avatar Jun 29 '22 03:06 michaelcuneo

The resulting type of persist() is PersistentStore (You also have a typing error, you forgot to indicate that you have an array of human, not just one)

So the right line is: public humans: PersistentStore<Array<humanType>> = persist(writable<Array<humanType>>([]), localStorage(), 'humans')


Let's write a bit more code (this is exactly the same result as before):

type listOfHuman = Array<hunanType> // The type of the data
const humansStore: Writable<listOfHuman> = writable([]); // The base store
const humans: PersistentStore<listOfHuman> = persist(humansStore, localStorage(), 'humans')` // Add the persist feature

And now some explanation (for the sake of readability, some parameter have been altered):

  • the function persist act as an high order function: it transform the input into a new object that inherit from it and add new feature
  • function persist<Y>(store: Writable<Y>, storage: StorageInterface<Y>, key: string): PersistentStore<Y>, Take as its first parameter a Writable store of subtype Y, and return a PersistentStore of subtype Y
  • function writable<T>(value?: T, start: StartStopNotifier<T> = noop): Writable<T>, Take as its first parameter a value of type T and return a Writable store of subtype T

The subtype allow to have a class/interface/function that can be specialized at runtime.

So to use PersistentStore, we have to match Y and T.

The goal is to have a persistant store that contains a list of humanType.

  • A list of humanType is this type Array<humanType> (a speciliazed version of Array that allow only humanType for element)
  • A persistant store of a list of humanType is the type PersistantStore<Array<humanType>>.

Now we have the target type.

Let's build the value:

  • to have a persistent store, we need to call the persist() function
  • the persist() function need a Writable object of the desire subtype (which is Array<humanType>, so the full type is Writable<Array<humanType>>)
  • the persist() function also need other parameter, but they are already correct (localStorage(), 'humans')
  • To have a Writable<Array<humanType>> object we need to call the writable() function with an initial value.

But as the initial value is an empty array ([]), the TypeScript compiler is unable to guess the correct type (as it only seen an Array not a specialized array), we have to help it by specifying the full type: writable<Array<humanType>>()

So to build the value we do: persist(writable<Array<humanType>>([]), localStorage(), 'humans')

Putting all together

const humans: PersistantStore<Array<humanType>> = persist(writable<Array<humanType>>([]), localStorage(), 'humans')

I hope that answer your question and help you to understand a bit how TypeScript work

MacFJA avatar Jun 30 '22 17:06 MacFJA

Wow, This is a very in-depth explanation, I have added 'Learn TypeScript' into my PRD for this year, and so far I've got variables down, but the rest looks very bad to read... I have been told that it is very good once you learn it properly, but I find that extremely hard to be easily readable, it does not look like clear concise code at all, but maybe that's just me.

This code line doesn't error anymore, and after reading it a few more times it does make sense. I was not aware of the 'PersistentStore' type, it wasn't in the documents anywhere that I can see.

michaelcuneo avatar Jul 05 '22 04:07 michaelcuneo

I was not aware of the 'PersistentStore' type, it wasn't in the documents anywhere that I can see.

You are right, the static documentation have most its examples (all svelte code) in plain JS and not in TypeScript.

And the generated documentation (npm run doc) is all about TypeScript.

I will update the README to at least list the exposed interface/type

MacFJA avatar Jul 05 '22 17:07 MacFJA