Home > Back-end >  Typescript: An object with any amount of keys or values
Typescript: An object with any amount of keys or values

Time:04-07

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.

  • Related