Last active
December 17, 2020 07:58
-
-
Save gcorreaq/593381b026aeb093dd3a866d15299875 to your computer and use it in GitHub Desktop.
Filter flavor text for the Poke API
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
fetch("https://pokeapi.co/api/v2/pokemon-species/2").then((result) => { | |
result.json().then((data) => { | |
// We filter the array of flavor texts only for the ones that have the language `en` | |
const fileterdFlavorTextEntries = data.flavor_text_entries.filter( | |
(element) => element.language.name === "en" | |
); | |
// If there's any entries, let's get the first one | |
const flavorTextEntry = fileterdFlavorTextEntries.length > 0 ? fileterdFlavorTextEntries[0] : {}; | |
console.log(flavorTextEntry); | |
// If we want, we can reassign the `flavor_text_entries` array to one with just the entry we have | |
data.flavor_text_entries = [flavorTextEntry]; | |
console.log(data); | |
// Or if we just want the flavor text itself | |
const flavorText = flavorTextEntry.flavor_text; | |
console.log(flavorText) | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This is an incomplete type declaration in purpose. I don't want to type the properties that I don't care about | |
type Pokemon = { | |
flavor_text_entries: FlavorTextEntry[], | |
} | |
// Half-way defined type, just for the sake of having the important bits | |
type FlavorTextEntry = { | |
flavor_text: string, | |
language: { | |
name: string, | |
}, | |
version: { | |
name: string, | |
} | |
}; | |
async function getPokeData(id: number): Promise<Pokemon> { | |
// This function just gives us the pokemon data | |
const result = await fetch(`https://pokeapi.co/api/v2/pokemon-species/${id}`); | |
return await result.json(); | |
} | |
function getFlavorText(pokemon: Pokemon): string | null { | |
// This will either return the flavor text for a pokemon, or just return null | |
// Get the filtered flavor text entries | |
const fileterdFlavorTextEntries: FlavorTextEntry[] = pokemon.flavor_text_entries.filter(element => element.language.name === 'en'); | |
// Get the first entry (if we got any) | |
return fileterdFlavorTextEntries?.[0]?.flavor_text; | |
} | |
getPokeData(2).then(pokemon => { | |
const flavorText = getFlavorText(pokemon); | |
console.log(flavorText) | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This is an incomplete type declaration in purpose. I don't want to type the properties that I don't care about | |
type Pokemon = { | |
flavor_text_entries: FlavorTextEntry[], | |
name: string, | |
names: NameEntry[], | |
order: number, | |
}; | |
// Basic type for types that will have language data | |
type LanguageData = { | |
language: { | |
name: string, | |
}, | |
}; | |
// Half-way defined type, just for the sake of having the important bits | |
// Note that we merge this type declaration with LanguageData to have all the properties we need | |
type FlavorTextEntry = { | |
flavor_text: string, | |
version: { | |
name: string, | |
}, | |
} & LanguageData; | |
// Half-way defined type, just for the sake of having the important bits | |
// Note that we merge this type declaration with LanguageData to have all the properties we need | |
type NameEntry = { | |
name: string, | |
} & LanguageData; | |
async function getPokeData(id: number): Promise<Pokemon> { | |
const result = await fetch(`https://pokeapi.co/api/v2/pokemon-species/${id}`); | |
return await result.json(); | |
} | |
function getFieldText<T extends LanguageData, K extends keyof T>(data: T[], field: K): T[K] | null { | |
/* | |
This function is generic: It filters the array `data[]` (with whatever types it has) | |
where `data[].language.name` is in English, and from the first entry it found, it will return the value | |
in the property `field` | |
For example: | |
data = [ | |
{ | |
language: { | |
name: 'en' | |
} | |
name: 'Gonchimon' | |
}, | |
{ | |
language: { | |
name: 'es' | |
}, | |
name: 'El terrible Gonchimon' | |
} | |
] | |
T is the type given by each object, and it extends LanguageData (because each object has a `language` property) | |
K will be any property of any of the objects in the array data (so, any key from any T in the array data) | |
It will return any value from one of the properties of the objects `T` in data, or null if nothing was found | |
*/ | |
const fileterdTextEntries = data.filter(element => element.language.name === 'en'); | |
return fileterdTextEntries.length > 0 ? fileterdTextEntries[0][field] : null; | |
} | |
getPokeData(2).then(pokemon => { | |
console.log(`Got data for pokemon with ID ${pokemon.order}`) | |
// The magic of typing the function `getFieldText` comes up when typechecking: here we cannot use as a second parameter | |
// something that is not defined in the type for the field `names` (the type `NameEntry` only defines properties `name` | |
// and `language`) | |
const pokemonName = getFieldText(pokemon.names, 'name'); | |
console.log(`The pokemon's name is ${pokemonName}`); | |
// The magic of typing the function `getFieldText` comes up when typechecking: here we cannot use as a second parameter | |
// something that is not defined in the type for the field `flavor_text_entries` (the type `FlavorTextEntry` only defines | |
// the properties `flavor_text`, `language` or `version`) | |
const flavorText = getFieldText(pokemon.flavor_text_entries, 'flavor_text'); | |
console.log(`The pokemon's flavor text is ${flavorText}`); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment