You may now notice an type error with getPokemon:
Type 'BuildPokeApiUrl | PokemonCollection' is not assignable to type 'never'.That's because we manually defined the PokeApiImpl interface, which doesn't conform anymore with the new implementation (no dependencies expected):
Every time you see a type issue in the form
Type 'Service' is not assignable to type 'never'it probably has to do with missing/outdated dependencies (in this exampleBuildPokeApiUrlandPokemonCollection)
interface PokeApiImpl {
/// `getPokemon` has `never` as dependencies
/// (`never` is the default type when not defined)
///
/// But our implementation uses `BuildPokeApiUrl` and `PokemonCollection`
/// ⛔️ Not assignable to `never`!
readonly getPokemon: Effect.Effect<
Pokemon,
FetchError | JsonError | ParseResult.ParseError | ConfigError
>;
}
export class PokeApi extends Context.Tag("PokeApi")<PokeApi, PokeApiImpl>() {Having to keep implementation and types in sync is a pain, we do not want to do this. It's faster to just derive the types from the actual implementation.
Good news! We can do this with typescript using typeof.
We first define a make value that contains the implementation of the service, and we provide its type definition when creating the Context service:
const make = {
getPokemon: Effect.gen(function* () {
const pokemonCollection = yield* PokemonCollection;
const buildPokeApiUrl = yield* BuildPokeApiUrl;
const requestUrl = buildPokeApiUrl({ name: pokemonCollection[0] });
const response = yield* Effect.tryPromise({
try: () => fetch(requestUrl),
catch: () => new FetchError(),
});
if (!response.ok) {
return yield* new FetchError();
}
const json = yield* Effect.tryPromise({
try: () => response.json(),
catch: () => new JsonError(),
});
return yield* Schema.decodeUnknown(Pokemon)(json);
}),
};
export class PokeApi extends Context.Tag("PokeApi")<PokeApi, typeof make>() {
static readonly Live = PokeApi.of(make);
}Now the service type is implementation-driven: we can go ahead and focus on the implementation (and never have to type things manually when the language supports type inference).
This
make+typeofpattern is common and recommended in effect.
Since we changed the service type we also need to update the
Testimplementation.We are going to fix the tests in an upcoming lesson 🔜
