electron-store icon indicating copy to clipboard operation
electron-store copied to clipboard

Typescript:schema type error

Open BeginsDuang opened this issue 4 years ago • 4 comments

QQ截图20200528134825

import ElectronStore = require('electron-store') //error

Version: electron-store: 5.1.1 typescript:3.9.4 node:14.3.0 electron:9.0.0

BeginsDuang avatar May 28 '20 08:05 BeginsDuang

The problem here is that typings of JSONSchema expect a subset of strings to be used as a type value ("string", "number", etc.). TypeScript, however, assumes that mutable strings are of type string so that you can change the value at any time without type errors.

In order to be able to use it in the schema option you just need to ensure TS the schema object is not going to be mutated. You can do it in two ways.

  1. Mark the schema object as a constant.
const schema = { ... } as const
  1. Pass the object directly into the Store.
const store = new ElectronStore({ schema: { /* your schema */ } })

mateuszkocz avatar Jun 13 '20 12:06 mateuszkocz

@mateuszkocz way 2 works for me. thanks!

riemannulus avatar Jun 19 '20 04:06 riemannulus

Or you may use interface like this

export interface Schema {
    someString: string;
    someListOfStrings: Array<string>
}

const store = new Store<Schema>()

khatskelevich avatar May 27 '21 13:05 khatskelevich

The problem here is that typings of JSONSchema expect a subset of strings to be used as a type value ("string", "number", etc.). TypeScript, however, assumes that mutable strings are of type string so that you can change the value at any time without type errors.

In order to be able to use it in the schema option you just need to ensure TS the schema object is not going to be mutated. You can do it in two ways.

  1. Mark the schema object as a constant.
const schema = { ... } as const
  1. Pass the object directly into the Store.
const store = new ElectronStore({ schema: { /* your schema */ } })

Option 1 here didn't quite work for me, because ElectronStore expects a non-const object.

Option 2 didn't work because I wanted to access things in my schema, like using the minimum/maximum for numeric inputs, and inlining the object like that prevents me from doing so.

Using an interface and electron-store's Schema type to do const schema: Schema<MyInterface> didn't work because it widens the schema's type—all the schemas, instead of being typed as written are now JSONSchema | boolean which is a pain.

Ultimately I combined these: use as const to keep the strong string literals, then remove the readonlys when giving it to the store. Hopefully, the store doesn't actually mutate that object (in which case it should really just take it as const):

const schema = {
  // ...
} as const;

// https://stackoverflow.com/a/43001581
type DeepWriteable<T> = { -readonly [P in keyof T]: DeepWriteable<T[P]> };

const store = new Store({ schema: schema as DeepWriteable<typeof schema> });

MHebes avatar Aug 03 '22 18:08 MHebes