I am trying to make a store function and set up types for each instance that I want to make. So I started with the following:
interface Store<Value> {
get: () => Value,
set: (n: Partial<Value>) => void
}
const createStore = (initialStore: any) => {
let store = initialStore
const get = () => store
const set = (newStore: any) => {
store = {
...store,
...newStore
}
}
return {
get,
set
}
}
const defaultOptions = {
x: 0,
y: 0
}
interface Options {
x: number,
y: number | null
}
const options: Store<Options> = createStore({...defaultOptions})
But obviously if you were to do the following typescript would allow it but it would be problematic.
const store = createStore('hello')
options.set('ho')
console.log(store.get())
You would run into problems logging something like this:
{
"0": "h",
"1": "o",
"2": "l",
"3": "l",
"4": "o"
}
But if I specify Object
or object
to the createStore function like const createStore = (initialStore: object) => {}
then I get an error:
Type '{ get: () => Object; set: (newStore: any) => void; }' is not assignable to type 'Store<Options>'.
The types returned by 'get()' are incompatible between these types.
The 'Object' type is assignable to very few other types. Did you mean to use the 'any' type instead?
Type 'Object' is missing the following properties from type 'Options': a, b
So how do I make sure that only an object is passed through but with any type of keys and values?
I have also tried
interface StoreArgs {
[key: string]: any
}
I get the following error
Type '{ get: () => StoreArgs; set: (newStore: any) => void; }' is not assignable to type 'Store<Options>'.
The types returned by 'get()' are incompatible between these types.
Type 'StoreArgs' is missing the following properties from type 'Options': a, b
CodePudding user response:
You could utilise generics and then specify that the type extends
object on the createStore
function.
For example:
const createStore = <T extends object>(initialStore: T): Store<T> => {
let store = initialStore
const get = () => store
const set = (newStore: Partial<T>) => {
store = {
...store,
...newStore
}
}
return {
get,
set
}
}
This will let you call createStore
with any value that extends 'object' as you want rather than strictly saying that the initialStore
value MUST be only an object.