Composable Dynamic Return Values

I am working with an Ionic Vue TypeScript site. I am still in very much in the early learning and trying things out stage but I am slowly working towards moving an old site we have to something more modern with the ability to run on more devices.

Following along with Vue Mastery - Coding Better Composables 3 of 5 - The Pattern of Dynamic Return Values and I can not figure out how to get this to work.

The composable, dataStorage.ts

import { Storage } from '@ionic/storage';

const ds = new Storage();

export default function (options?: any) {
  const { exposeGet = true } = (options ?? {exposeGet: true});

  const initStoreage = async function () {
    return await ds.create();
  }  

  const getData = async function(key: string) {
    return await ds.get(key);
  };

  const saveData = async function (key: string, value: string) {
    return await ds.set(key, value);
  };

  if (ds.driver === null) initStoreage();

  if ( exposeGet ) {
console.log("Both");
    return { getData, saveData };
  } else {
console.log("SaveData");
    return saveData;
  }
}

I then imported it:

import store from '@/other/dataStorage';

And used it:

        const sd = store();

        sd('a',this.$route.path);

Which results in the following error:

[vue-cli-service] ERROR in src/components/BaseLayout.vue:54:9
[vue-cli-service] TS2349: This expression is not callable.
[vue-cli-service]   Not all constituents of type '((key: string, value: string) => Promise<any>) | { getData: (key: string) => Promise<any>; saveData: (key: string, value: string) => Promise<any>; }' are callable.
[vue-cli-service]     Type '{ getData: (key: string) => Promise<any>; saveData: (key: string, value: string) => Promise<any>; }' has no call signatures.
[vue-cli-service]     52 |         const sd = store();
[vue-cli-service]     53 |
[vue-cli-service]   > 54 |         sd('a',this.$route.path);
[vue-cli-service]        |         ^^
[vue-cli-service]     55 |                

Yet when I comment out the multiple return lines:

  // if ( exposeGet ) {
// console.log("Both");
    // return { getData, saveData };
  // } else {
console.log("SaveData");
    return saveData;
  // }

It gives a couple of warnings, which make sense because of the now commented out code, but it runs:

[vue-cli-service] /Users/peterb/Desktop/ionic/diary2/src/other/dataStorage.ts
[vue-cli-service]    6:11  warning  'exposeGet' is assigned a value but never used  @typescript-eslint/no-unused-vars
[vue-cli-service]   12:9   warning  'getData' is assigned a value but never used    @typescript-eslint/no-unused-vars

At this stage I think I have not done something properly with the typescript aspect of this. [Note: I thought it was something to do with the Promise but when I removed all the async/awaits from the composable I was still getting the same error]

Any thoughts/help/tips would be most appreciated.

In case anyone else finds this I finally found a solution that works for me. I would still like to understand what I am missing with trying to get “Dynamic Return” working with typescript, but that is a future endeavour.

import { Storage } from '@ionic/storage';

const ds = new Storage();

export default function () {  
  const initStorage = async function () {
    return await ds.create();
  }  

  const storage = {
    getData:  async <T>(key: string): Promise<T> => {
      return await ds.get(key);
    },
    saveData: async (key: string, value: any): Promise<void> => {
      await ds.set(key, value);
    },
    clearData: async (): Promise<void> => {
      await ds.clear();
    }
  }

  if (ds.driver === null) initStorage();

  return storage;
}

By returning one object I was then able to put the all the methods I wanted on the object.

1 Like