Paul A
Paul A

Reputation: 417

Cannot apply typescript type to a derived svelte store

I have a working dervived store called selectedDocument in svelte. I am getting the following TS linting error when I attempt to add the correct type to it. (And the intellisense is not working)

TS Linting errors

on the definition of the selectedDocument store

Expected 2 type arguments, but got 1.ts(2558)

on ([$selectedDocId, $userDocuments])

Type '{ view_id: never; user_id: never; doc_id: never; user_name: never; user_avatar: never; cardMap: never; cards: never; }' must have a '[Symbol.iterator]()' method that returns an iterator.ts(2488)

THE CODE

The store works and the type works with other similar data

Interfaces

export interface MainView {
  view_id: string;
  user_id: string;
  doc_id: string;
  user_name: string;
  user_avatar: string;
  cardMap: CardMap;
  cards: {
    [key: string]: Card;
  };
}
export interface Document {
    doc_id: string;
    createDate: Date;
    createdBy: string;
    title: string;
  }
  

Stores

const userDocuments = writable<Document[]>(); 

const selectedDocId = writable<string>(""); // Selected doucment Id

const selectedDocument = derived<Document>(
  [selectedDocId, userDocuments],
  ([$selectedDocId, $userDocuments]) =>
    getObjByIdReturnOneObj($userDocuments, $selectedDocId, "doc_id")
);

The function getObjByIdReturnOneObj takes in the array of documents and returns a single object (not in an array)

export interface MainView {
  view_id: string;
  user_id: string;
  doc_id: string;
  user_name: string;
  user_avatar: string;
  cardMap: CardMap;
  cards: {
    [key: string]: Card;
  };
}
export interface Document {
    doc_id: string;
    createDate: Date;
    createdBy: string;
    title: string;
  }
  

Stores

const userDocuments = writable<Document[]>(); 

const selectedDocId = writable<string>(""); // Selected doucment Id

const selectedDocument = derived<Document>(
  [selectedDocId, userDocuments],
  ([$selectedDocId, $userDocuments]) =>
    getObjByIdReturnOneObj($userDocuments, $selectedDocId, "doc_id")
);

The function getObjByIdReturnOneObj takes in the array of documents and returns a single object (not in an array)

Upvotes: 3

Views: 3033

Answers (1)

brunnerh
brunnerh

Reputation: 184336

If you look at the type of derived, you will see that it has two type arguments. This is its simplest signature:

export declare function derived<S extends Stores, T>(
  stores: S,
  fn: (values: StoresValues<S>) => T
): Readable<T>;

Currently you cannot only specify some of the type arguments, it is all or nothing. Generally, I would recommend not specifying the arguments when they can be derived automatically; it mostly just adds unnecessary noise.

In this case the second argument has to have the return type of getObjByIdReturnOneObj if you specify the types.

The first one also has to be adjusted to include at least Readable as Stores is defined as:

declare type Stores =
  Readable<any> |
  [Readable<any>, ...Array<Readable<any>>] |
  Array<Readable<any>>;

When setting the types you can also use typeof to derive types from the existing stores and the function:

const selectedDocument = derived<
    [typeof selectedDocId, typeof userDocuments],
    ReturnType<typeof getObjByIdReturnOneObj>
>(...)

Or manually something like:

const selectedDocument = derived<
    [Readable<string>, Readable<Document[]>],
    Document // Based on type specified in question
>(...)

Upvotes: 9

Related Questions