Skip to content

Latest commit

 

History

History
94 lines (77 loc) · 2.52 KB

typescript.md

File metadata and controls

94 lines (77 loc) · 2.52 KB

Using resourcerer with TypeScript

Note: TypeScript support is in beta. Please file any bugs.

Resourcerer is ⚡⚡⚡ with TypeScript, but requires one extra step in your config file:

// js/core/resourcerer-config.ts
import {ModelMap} from 'resourcerer';
import TodosCollection from 'js/models/todos-collection';
import UserTodosCollection from 'js/models/users-todos-collection';

/**
 * Because the ModelMap is populated in user-land, we have to annotate its types here, as well.
 * Add your model types to this interface declaration, which will be merged with the interface
 * in the library.
 *
 * I wish we didn't have to do this duplication, and maybe there's a way to do it without, but
 * I am not good enough at TypeScript to figure it out myself. If you can, please submit a PR!
 */
declare module 'resourcerer' {
  export interface ModelMap {
    todos: new () => TodosCollection,
    userTodos: new () => UserTodosCollection,
    // ...etc
  }
}

/ now add your models to the model map as normal
ModelMap.add({
  todos: TodosCollection,
  userTodos: UserTodosCollection,
  // ...etc
});

Note that you no longer need to add a resource key like USER_TODOS in the ModelMap, which would normally get auto-magically turned into the camelCase userTodos. Since TypeScript will enforce correctness, you can just use the string literal userTodos instead.

When defining your models, you can add schemas as generic types:

// js/models/todos-collection.ts
import {Collection} from 'resourcerer';

interface Todo {
  id: string;
  name: string;
}

export default TodosCollection extends Collection<Todo> {
  url() {
    return '/todos';
  }
}

and now you can use it in your components!

import {type ExecutorFunction, useResources} from 'resourcerer';

// you don't need to worry about resourceKeys anymore, you can just use the
// string literal! TypeScript will enforce correctness
const getResources: ExecutorFunction = (resourceKeys, props) => ({todos: {}});

function MyComponent(props) {
  const {
    isLoading,
    hasErrored,
    hasLoaded,
    // type: TodosCollection
    todosCollection
  } = useResources(getResources, props);

  return (
    <div className='MyComponent'>
      {isLoading ? <Loader /> : null}

      {hasErrored ? <ErrorMessage /> : null}

      {hasLoaded ? (
        <ul>
          {/** id and name are registered as string types, hurray! */}
          {todosCollection.toJSON().map(({id, name}) => (
            <li key={id}>{name}</li>
          ))}
        </ul>
      ) : null}
    </div>
  );
}