Skip to content

Using with TypeScript ​

vue-concurrency is written in TypeScript and therefore has a 1st class TypeScript support. In most cases the types should be correctly inferred.

ts
// Task<User, [string, number]>
const addUser = useTask(function*(signal, name: string, age: number) {
  return new User({ name, age });
});

If it's helpful, you can specify a task type explicitly:

ts
// the implementation of this task has to return User and take a string and number arguments
const addUser = useTask<User, [string, number]>(function*(signal, name, age) {
  return new User({ name, age });
});

Known limitations ​

Unfortunately, with current limitations of TypeScript it's not possible to correctly infer results of yield operations. That will leave any yielded value with type any. If possible, it's good to avoid return yield and do just return. But any intermediate values that were yielded have to be typed explicily:

ts
useTask(function*(signal) {
  const accounts: Account[] = yield someAjax('/accounts', { signal });
});

If you're using custom async functions it is possible to make this pattern a bit more generic. This pattern has been borrowed from redux-saga-typescript.

ts
import { YieldReturn } from 'vue-concurrency/src/Task';

/* ... */

useTask(function*(signal) {
  const accounts: YieldReturn<typeof getAccounts> = yield getAccounts({ signal });
});

This will make accounts the same type as what the Promise from getAccounts resolves to. The same approach can be used for performing tasks:

ts
useTask(function*() {
  const accounts: YieldReturn<typeof getAccountsTask> = yield getAccountsTask.perform();
});

As an alternative, there's also useAsyncTask() for which there's no issue of typing awaited values:

ts
useAsyncTask(function*() {
  const accounts = await getAccountsTask.perform(); // correct typing here
});

It can be used if cancelation is not a priority.