Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
michaelcuneo opened this issue Jun 29, 2022 · 3 comments · Fixed by #22
Closed

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

michaelcuneo opened this issue Jun 29, 2022 · 3 comments · Fixed by #22

Comments

@michaelcuneo
Copy link

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

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.

@MacFJA
Copy link
Owner

MacFJA commented Jun 30, 2022

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

@michaelcuneo
Copy link
Author

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.

@MacFJA
Copy link
Owner

MacFJA commented Jul 5, 2022

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants