Skip to content

Commit

Permalink
fix: update types
Browse files Browse the repository at this point in the history
  • Loading branch information
DiogoAbu committed Apr 4, 2021
1 parent 98b5a72 commit 8bbd882
Show file tree
Hide file tree
Showing 8 changed files with 42 additions and 27 deletions.
2 changes: 0 additions & 2 deletions jest/jest-setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ jest.mock('react-native/Libraries/EventEmitter/NativeEventEmitter.js', () => {
// Fix for `useNativeDriver` is not supported because the native animated module is missing.
jest.mock('react-native/Libraries/Animated/NativeAnimatedHelper');

jest.mock('@react-native/polyfills/error-guard.js');

jest.mock('@react-native-community/masked-view', () => ({}));

jest.mock('react-native-bootsplash', () => {
Expand Down
4 changes: 2 additions & 2 deletions src/components/MoveItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ const MoveItem: ListRenderItem<IPokemonMove> = ({ item, index }) => {
} else if (learnMethodName === 'machine') {
learn = `Learn by using: ${machineItem?.names?.find((e) => e.language.name === 'en')?.name ?? '...'}`;
} else if (learnMethodName === 'egg') {
learn = `Learn by breeding`;
learn = 'Learn by breeding';
} else if (learnMethodName === 'tutor') {
learn = `Learn by tutoring`;
learn = 'Learn by tutoring';
}

if (!move && index >= 10) {
Expand Down
6 changes: 4 additions & 2 deletions src/hooks/use-method.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useCallback, useLayoutEffect, useRef } from 'react';

type Callback<Args extends any[], Result> = (...args: Args) => Result;
type Callback<Args extends never[], Result> = (...args: Args) => Result;

/**
* Create callback that keeps the same reference during entire lifecycle of the component while having access to fresh
Expand All @@ -10,7 +10,9 @@ type Callback<Args extends any[], Result> = (...args: Args) => Result;
*
* If you want to call it during the render - you probably don't need to memoize the function or using `useCallbacl` might be more suitable
*/
function useMethod<Args extends any[], Result>(callback: Callback<Args, Result>): (...args: Args) => Result {
function useMethod<Args extends never[], Result>(
callback: Callback<Args, Result>,
): (...args: Args) => Result {
const lastRenderCallbackRef = useRef<Callback<Args, Result>>(callback);

const methodLikeCallback = useCallback((...args: Args) => {
Expand Down
21 changes: 12 additions & 9 deletions src/hooks/use-poke-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,11 @@ export default function usePokeApi<
setData((prev) => {
return {
...responseData,
results: [...((prev as any)?.results || []), ...(responseData as any)?.results],
} as any;
results: [
...((prev as Record<string, never>)?.results || []),
...(responseData as Record<string, never>)?.results,
],
} as ResponseData;
});
} else {
// Overwrite data
Expand Down Expand Up @@ -170,7 +173,7 @@ export default function usePokeApi<
};
}

export async function resolve<ResponseData = any>({
export async function resolve<ResponseData = never>({
endpoint,
id,
page,
Expand All @@ -197,14 +200,14 @@ export async function resolve<ResponseData = any>({
// Get from api
if (id) {
// Fetch by id
responseData = await apiFetch({ endpoint, id, fetchOptions });
responseData = ((await apiFetch({ endpoint, id, fetchOptions })) as unknown) as ResponseData;
} else if (typeof page === 'number') {
if (page === 0) {
// Fetch all results
responseData = (await apiListAll({ endpoint, fetchOptions })) as any;
responseData = ((await apiListAll({ endpoint, fetchOptions })) as unknown) as ResponseData;
} else if (page > 0) {
// Fetch results by page
responseData = (await apiList({ endpoint, page, fetchOptions })) as any;
responseData = ((await apiList({ endpoint, page, fetchOptions })) as unknown) as ResponseData;
}
}

Expand Down Expand Up @@ -246,7 +249,7 @@ async function apiFetch({
fetchOptions?: RequestInit;
}) {
// @ts-ignore
const api = PokeAPI[endpoint] as EndpointClass<any>;
const api = PokeAPI[endpoint] as EndpointClass<typeof endpoint>;
return api.fetch(id, false, fetchOptions);
}

Expand All @@ -263,7 +266,7 @@ async function apiList({
fetchOptions?: RequestInit;
}) {
// @ts-ignore
const api = PokeAPI[endpoint] as EndpointClass<any>;
const api = PokeAPI[endpoint] as EndpointClass<typeof endpoint>;
const offset = (page - 1) * LIST_LIMIT;
return api.list(LIST_LIMIT, offset, fetchOptions);
}
Expand All @@ -279,6 +282,6 @@ async function apiListAll({
fetchOptions?: RequestInit;
}) {
// @ts-ignore
const api = PokeAPI[endpoint] as EndpointClass<any>;
const api = PokeAPI[endpoint] as EndpointClass<typeof endpoint>;
return api.listAll(false, fetchOptions);
}
4 changes: 2 additions & 2 deletions src/hooks/use-press.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import useMethod from './use-method';

type Callback<Args extends any[], Result> = (...args: Args) => Result;
type Callback<Args extends never[], Result> = (...args: Args) => Result;

export default function usePress<Args extends any[], Result>(
export default function usePress<Args extends never[], Result>(
callback: Callback<Args, Result>,
): (...args: Args) => Result {
return useMethod(callback);
Expand Down
26 changes: 18 additions & 8 deletions src/screens/Home/SearchList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { FlatList } from 'react-native';

import { useSafeAreaInsets } from 'react-native-safe-area-context';
import Bottleneck from 'bottleneck';
import { IApiResource, IName, IPokemonSpecies } from 'pokeapi-typescript';
import { IApiResource, IName, IPokemon, IPokemonSpecies } from 'pokeapi-typescript';
import stringSimilarity from 'string-similarity';

import Icon from '!/components/Icon';
Expand All @@ -23,6 +23,12 @@ const limiter = new Bottleneck({

const keyExtractor = (item: SearchResult) => `${item.type}/${item.name}/${String(item.id)}`;

type CommonResponse = {
id: number;
names: IName[];
species?: IPokemon['species'];
};

type SearchResult = {
id: number;
name: string;
Expand Down Expand Up @@ -108,6 +114,7 @@ const SearchList: FC<SearchListProps> = ({ searchQuery, setIsSearchbarLoading })
renderCenter={
<>
<Text style={styles.searchListItemTitle}>{item.name}</Text>

<Text>{item.type}</Text>
</>
}
Expand All @@ -120,10 +127,10 @@ const SearchList: FC<SearchListProps> = ({ searchQuery, setIsSearchbarLoading })
);
};

async function getResults(
async function getResults<Response extends unknown>(
searchQuery: string,
endpoint: PokeApiEndpoint,
results: IApiResource<any>[],
results: IApiResource<Response>[],
setResults: React.Dispatch<React.SetStateAction<SearchResult[]>>,
setIsSearchbarLoading: React.Dispatch<React.SetStateAction<boolean>>,
): Promise<void> {
Expand All @@ -135,12 +142,13 @@ async function getResults(
return;
}

// Limit api calls
const resultsFound = await limiter.schedule(async () => {
setIsSearchbarLoading(true);

// For each api result get search result data
const tasks = results.map(async (each) => {
return resolveOneResource(each, searchQuery, endpoint);
return resolveOneResource<IApiResource<Response>>(each, searchQuery, endpoint);
});

return Promise.all(tasks);
Expand All @@ -161,13 +169,15 @@ async function getResults(
}
}

async function resolveOneResource(
each: any,
async function resolveOneResource<Each = unknown, Response extends CommonResponse = CommonResponse>(
resource: Each,
searchQuery: string,
endpoint: PokeApiEndpoint,
): Promise<SearchResult | null> {
try {
const resourceName = (each.name as string).toLowerCase().replace(/[^a-z0-9]/g, ' ');
const each = (resource as unknown) as Record<string, string>;

const resourceName = each.name.toLowerCase().replace(/[^a-z0-9]/g, ' ');
const nameWords = resourceName.split(' ');

const query = searchQuery.toLowerCase().replace(/[^a-z0-9]/g, ' ');
Expand All @@ -176,7 +186,7 @@ async function resolveOneResource(
}

// Get main data
const data = await resolve<any>({
const data = await resolve<Response>({
endpoint,
id: getIdFromUrl(each.url),
});
Expand Down
2 changes: 1 addition & 1 deletion src/screens/PokemonDetails/BaseStats.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ interface Props {
const BaseStats: FC<Props> = ({ pokemon, displayFooterImage }) => {
const baseStats: Record<BaseStatNames, number> = pokemon.stats.reduce((prev, curr) => {
return { ...prev, [curr.stat.name]: curr.base_stat };
}, {} as any);
}, {} as Record<BaseStatNames, number>);

return (
<>
Expand Down
4 changes: 3 additions & 1 deletion src/utils/not-empty.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
export default function notEmpty<TValue>(value: TValue | null | undefined): value is TValue {
if (value === null || value === undefined) return false;
if (value === null || value === undefined) {
return false;
}
// @ts-ignore
const testDummy: TValue = value;
return true;
Expand Down

0 comments on commit 8bbd882

Please sign in to comment.