Merge pull request #3310 from inaturalist/mob-1043-lint-rule-for-enforcing-consistent-array-type-definition

Mob 1043 lint rule for enforcing consistent array type definition
This commit is contained in:
Abbey Campbell
2025-12-22 19:25:29 -08:00
committed by GitHub
61 changed files with 113 additions and 110 deletions

View File

@@ -129,6 +129,9 @@ module.exports = {
// https://eslint.org/docs/latest/rules/no-undef#handled_by_typescript // https://eslint.org/docs/latest/rules/no-undef#handled_by_typescript
"no-undef": "error", "no-undef": "error",
"@typescript-eslint/array-type": ["error", {
default: "array",
}],
"@typescript-eslint/no-unused-vars": [ "@typescript-eslint/no-unused-vars": [
"error", "error",
{ {

View File

@@ -65,12 +65,12 @@ export interface ErrorWithResponse {
url: string; url: string;
json: () => Promise<{ json: () => Promise<{
status: string; status: string;
errors: Array<{ errors: {
errorCode: string; errorCode: string;
message: string; message: string;
from: string | null; from: string | null;
stack: string | null; stack: string | null;
}>; }[];
}>; }>;
}; };
status?: number; status?: number;

View File

@@ -66,10 +66,10 @@ const fetchRemoteObservation = async (
}; };
const fetchRemoteObservations = async ( const fetchRemoteObservations = async (
uuids: Array<string>, uuids: string[],
params: Object = {}, params: Object = {},
opts: Object = {}, opts: Object = {},
): Promise<?Array<Object>> => { ): Promise<?Object[]> => {
try { try {
const response = await inatjs.observations.fetch( const response = await inatjs.observations.fetch(
uuids, uuids,

View File

@@ -5,7 +5,7 @@ import inatjs from "inaturalistjs";
import handleError from "./error"; import handleError from "./error";
const fetchPlace = async ( const fetchPlace = async (
id: number | Array<number>, id: number | number[],
params: Object = {}, params: Object = {},
opts: Object = {}, opts: Object = {},
): Promise<?Object> => { ): Promise<?Object> => {

View File

@@ -47,7 +47,7 @@ function mapToLocalSchema( taxon ) {
} }
async function fetchTaxon( async function fetchTaxon(
id: number | Array<number>, id: number | number[],
params: Object = {}, params: Object = {},
opts: Object = {}, opts: Object = {},
): Promise<?Object> { ): Promise<?Object> {

View File

@@ -71,7 +71,7 @@ const fetchRemoteUser = async (
}; };
const fetchUsers = async ( const fetchUsers = async (
ids: Array<number>, ids: number[],
params: Object = {}, params: Object = {},
opts: Object = {}, opts: Object = {},
): Promise<?Object> => { ): Promise<?Object> => {

View File

@@ -21,7 +21,7 @@ const logger = log.extend( "App" );
type SharedItem = { type SharedItem = {
mimeType: string, mimeType: string,
data: string | Array<string> data: string | string[]
}; };
const handleShare = ( navigation, item: ?SharedItem ) => { const handleShare = ( navigation, item: ?SharedItem ) => {

View File

@@ -21,7 +21,7 @@ interface Props {
takingPhoto: boolean; takingPhoto: boolean;
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
takePhotoAndStoreUri: Function; takePhotoAndStoreUri: Function;
newPhotoUris: Array<object>; newPhotoUris: object[];
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
setNewPhotoUris: Function; setNewPhotoUris: Function;
takePhotoOptions: object; takePhotoOptions: object;

View File

@@ -53,7 +53,7 @@ type Props = {
takingPhoto: boolean, takingPhoto: boolean,
takePhotoAndStoreUri: Function, takePhotoAndStoreUri: Function,
takePhotoOptions: Object, takePhotoOptions: Object,
newPhotoUris: Array<Object>, newPhotoUris: Object[],
setNewPhotoUris: Function setNewPhotoUris: Function
}; };

View File

@@ -11,7 +11,7 @@ import { useTranslation } from "sharedHooks";
type Props = { type Props = {
canFetch?: boolean, canFetch?: boolean,
contentContainerStyle?: Object, contentContainerStyle?: Object,
data: Array<Object>, data: Object[],
fetchNextPage: boolean, fetchNextPage: boolean,
hideLoadingWheel: boolean, hideLoadingWheel: boolean,
isFetchingNextPage: boolean, isFetchingNextPage: boolean,

View File

@@ -57,7 +57,7 @@ type FullPageWebViewParams = {
title?: string; title?: string;
loggedIn?: boolean; loggedIn?: boolean;
skipSetSourceInShouldStartLoadWithRequest?: boolean; skipSetSourceInShouldStartLoadWithRequest?: boolean;
clickablePathnames?: Array<string>; clickablePathnames?: string[];
shouldLoadUrl?: ( url: string ) => boolean; shouldLoadUrl?: ( url: string ) => boolean;
} }

View File

@@ -31,16 +31,16 @@ type Props = {
onDeletePhoto?: Function, onDeletePhoto?: Function,
onClose?: Function, onClose?: Function,
onDeleteSound?: Function, onDeleteSound?: Function,
photos: Array<{ photos: {
id?: number, id?: number,
url: string, url: string,
localFilePath?: string, localFilePath?: string,
attribution?: string, attribution?: string,
licenseCode?: string licenseCode?: string
}>, }[],
sounds?: Array<{ sounds?: {
file_url: string file_url: string
}>, }[],
selectedMediaIndex: number, selectedMediaIndex: number,
setSelectedMediaIndex: Function setSelectedMediaIndex: Function
} }

View File

@@ -13,18 +13,18 @@ import useTranslation from "sharedHooks/useTranslation";
type Props = { type Props = {
isLargeScreen?: boolean, isLargeScreen?: boolean,
photos: Array<{ photos: {
id?: number, id?: number,
url: string, url: string,
localFilePath?: string, localFilePath?: string,
attribution?: string, attribution?: string,
licenseCode?: string licenseCode?: string
}>, }[],
scrollToIndex: Function, scrollToIndex: Function,
selectedMediaIndex?: number, selectedMediaIndex?: number,
sounds?: Array<{ sounds?: {
file_url: string file_url: string
}>, }[],
} }
const SMALL_ITEM_CLASS = "rounded-sm w-[42px] h-[42px] mx-[6px] my-[12px]"; const SMALL_ITEM_CLASS = "rounded-sm w-[42px] h-[42px] mx-[6px] my-[12px]";

View File

@@ -30,16 +30,16 @@ type Props = {
onClose?: Function, onClose?: Function,
onDeletePhoto?: Function, onDeletePhoto?: Function,
onDeleteSound?: Function, onDeleteSound?: Function,
photos?: Array<{ photos?: {
id?: number, id?: number,
url: string, url: string,
localFilePath?: string, localFilePath?: string,
attribution?: string, attribution?: string,
licenseCode?: string licenseCode?: string
}>, }[],
sounds?: Array<{ sounds?: {
file_url: string file_url: string
}>, }[],
uri?: string | null uri?: string | null
} }

View File

@@ -14,16 +14,16 @@ type Props = {
onClose?: Function, onClose?: Function,
onDeletePhoto?: Function, onDeletePhoto?: Function,
onDeleteSound?: Function, onDeleteSound?: Function,
photos?: Array<{ photos?: {
id?: number, id?: number,
url: string, url: string,
localFilePath?: string, localFilePath?: string,
attribution?: string, attribution?: string,
licenseCode?: string licenseCode?: string
}>, }[],
sounds?: Array<{ sounds?: {
file_url: string file_url: string
}>, }[],
showModal: boolean, showModal: boolean,
uri?: string | null uri?: string | null
} }

View File

@@ -253,7 +253,7 @@ const MyObservationsContainer = ( ): React.FC => {
const [activeTab, setActiveTab] = useState( OBSERVATIONS_TAB ); const [activeTab, setActiveTab] = useState( OBSERVATIONS_TAB );
let numTotalTaxaLocal: number | undefined; let numTotalTaxaLocal: number | undefined;
const localObservedSpeciesCount: Array<SpeciesCount> = []; const localObservedSpeciesCount: SpeciesCount[] = [];
if ( !currentUser ) { if ( !currentUser ) {
// Calculate obs and leaf taxa counts from local observations // Calculate obs and leaf taxa counts from local observations
const distinctTaxonObs = realm.objects<RealmObservation>( "Observation" ) const distinctTaxonObs = realm.objects<RealmObservation>( "Observation" )

View File

@@ -11,7 +11,7 @@ import ActivityItem from "./ActivityItem";
type Props = { type Props = {
observation:Object, observation:Object,
refetchRemoteObservation: Function, refetchRemoteObservation: Function,
activityItems: Array<Object>, activityItems: Object[],
openAgreeWithIdSheet: Function, openAgreeWithIdSheet: Function,
isConnected: boolean, isConnected: boolean,
targetItemID: number, targetItemID: number,

View File

@@ -14,12 +14,12 @@ const sectionClass = "mx-[15px] mb-[20px]";
// TODO: can we get a centralized type/interface for our realm objects, here observation and project // TODO: can we get a centralized type/interface for our realm objects, here observation and project
interface Props { interface Props {
observation: { observation: {
project_observations: Array<{ project_observations: {
project: object; project: object;
}>; }[];
non_traditional_projects: Array<{ non_traditional_projects: {
project: object; project: object;
}>; }[];
}; };
} }

View File

@@ -31,7 +31,7 @@ import SuggestIDSheet from "./Sheets/SuggestIDSheet";
const isTablet = DeviceInfo.isTablet(); const isTablet = DeviceInfo.isTablet();
type Props = { type Props = {
activityItems: Array<Object>, activityItems: Object[],
addingActivityItem: Function, addingActivityItem: Function,
closeAgreeWithIdSheet: Function, closeAgreeWithIdSheet: Function,
belongsToCurrentUser: boolean, belongsToCurrentUser: boolean,
@@ -63,7 +63,7 @@ type Props = {
showSuggestIdSheet: boolean, showSuggestIdSheet: boolean,
subscriptions?: Object, subscriptions?: Object,
suggestIdSheetDiscardChanges: Function, suggestIdSheetDiscardChanges: Function,
tabs: Array<Object>, tabs: Object[],
identBodySheetShown?: boolean, identBodySheetShown?: boolean,
onCloseIdentBodySheet?: Function, onCloseIdentBodySheet?: Function,
newIdentification?: null | { newIdentification?: null | {

View File

@@ -12,16 +12,16 @@ import SoundContainer from "./SoundContainer";
type Props = { type Props = {
loading: boolean, loading: boolean,
photos: Array<{ photos: {
id?: number, id?: number,
url: string, url: string,
localFilePath?: string, localFilePath?: string,
attribution?: string, attribution?: string,
licenseCode?: string licenseCode?: string
}>, }[],
sounds?: Array<{ sounds?: {
file_url: string file_url: string
}>, }[],
tablet: boolean tablet: boolean
} }

View File

@@ -16,8 +16,8 @@ import ObsMedia from "./ObsMedia";
type Props = { type Props = {
loading: boolean, loading: boolean,
photos: Array<Object>, photos: Object[],
sounds: Array<Object>, sounds: Object[],
tablet: boolean tablet: boolean
} }

View File

@@ -11,7 +11,7 @@ import ActivityItem from "./ActivityItem";
type Props = { type Props = {
observation:Object, observation:Object,
refetchRemoteObservation: Function, refetchRemoteObservation: Function,
activityItems: Array<Object>, activityItems: Object[],
openAgreeWithIdSheet: Function, openAgreeWithIdSheet: Function,
isConnected: boolean, isConnected: boolean,
targetItemID: ?number, targetItemID: ?number,

View File

@@ -6,12 +6,12 @@ import React, { useMemo } from "react";
// TODO: can we get a centralized type/interface for our realm objects, here observation and project // TODO: can we get a centralized type/interface for our realm objects, here observation and project
interface Props { interface Props {
observation: { observation: {
project_observations: Array<{ project_observations: {
project: object; project: object;
}>; }[];
non_traditional_projects: Array<{ non_traditional_projects: {
project: object; project: object;
}>; }[];
}; };
} }

View File

@@ -27,7 +27,7 @@ import StatusSection from "./StatusSection/StatusSection";
const cardClassBottom = "rounded-b-2xl border-lightGray border-[2px] pb-3 border-t-0 -mt-0.5 mb-4"; const cardClassBottom = "rounded-b-2xl border-lightGray border-[2px] pb-3 border-t-0 -mt-0.5 mb-4";
type Props = { type Props = {
activityItems: Array<object>; activityItems: object[];
addingActivityItem: boolean; addingActivityItem: boolean;
belongsToCurrentUser: boolean; belongsToCurrentUser: boolean;
currentUser: RealmUser; currentUser: RealmUser;

View File

@@ -11,16 +11,16 @@ import SoundContainer from "./SoundContainer";
type Props = { type Props = {
loading: boolean, loading: boolean,
photos: Array<{ photos: {
id?: number, id?: number,
url: string, url: string,
localFilePath?: string, localFilePath?: string,
attribution?: string, attribution?: string,
licenseCode?: string licenseCode?: string
}>, }[],
sounds?: Array<{ sounds?: {
file_url: string file_url: string
}> }[]
} }
const ObsMedia = ( { const ObsMedia = ( {

View File

@@ -16,8 +16,8 @@ import ObsMedia from "./ObsMedia";
type Props = { type Props = {
loading: boolean, loading: boolean,
photos: Array<Object>, photos: Object[],
sounds: Array<Object> sounds: Object[]
} }
const ObsMediaDisplay = ( { const ObsMediaDisplay = ( {

View File

@@ -22,7 +22,7 @@ const { useRealm } = RealmContext;
type Props = { type Props = {
passesEvidenceTest: boolean; passesEvidenceTest: boolean;
observations: Array<object>; observations: object[];
currentObservation: RealmObservation; currentObservation: RealmObservation;
currentObservationIndex: number; currentObservationIndex: number;
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type

View File

@@ -27,13 +27,13 @@ const logger = log.extend( "EvidenceList" );
type Props = { type Props = {
handleAddEvidence?: Function, handleAddEvidence?: Function,
observationSounds?: Array<{ observationSounds?: {
id?: number, id?: number,
sound: { sound: {
file_url: string, file_url: string,
}, },
uuid: string uuid: string
}> }[]
} }
const EvidenceList = ( { const EvidenceList = ( {

View File

@@ -20,18 +20,18 @@ import AddEvidenceSheet from "./Sheets/AddEvidenceSheet";
type Props = { type Props = {
currentObservation: Object, currentObservation: Object,
isFetchingLocation: boolean, isFetchingLocation: boolean,
locationTextClassNames: Array<string>, locationTextClassNames: string[],
passesEvidenceTest: Function, passesEvidenceTest: Function,
observationPhotos: Array<Object>, observationPhotos: Object[],
setShowAddEvidenceSheet: Function, setShowAddEvidenceSheet: Function,
showAddEvidenceSheet: boolean, showAddEvidenceSheet: boolean,
observationSounds?: Array<{ observationSounds?: {
id?: number, id?: number,
sound: { sound: {
file_url: string, file_url: string,
}, },
uuid: string uuid: string
}>, }[],
onLocationPress: ( ) => void, onLocationPress: ( ) => void,
updateObservationKeys: Function updateObservationKeys: Function
} }

View File

@@ -10,7 +10,7 @@ import { useTranslation } from "sharedHooks";
type Props = { type Props = {
currentObservationIndex: number, currentObservationIndex: number,
setCurrentObservationIndex: Function, setCurrentObservationIndex: Function,
observations: Array<Object>, observations: Object[],
setResetScreen: Function, setResetScreen: Function,
transitionAnimation: Function, transitionAnimation: Function,
transitionAnimationRef: Object transitionAnimationRef: Object

View File

@@ -21,7 +21,7 @@ import DiscardObservationSheet from "./Sheets/DiscardObservationSheet";
const { useRealm } = RealmContext; const { useRealm } = RealmContext;
type Props = { type Props = {
observations: Array<Object>, observations: Object[],
currentObservation: Object currentObservation: Object
} }

View File

@@ -15,7 +15,7 @@ const { useRealm } = RealmContext;
type Props = { type Props = {
currentObservation: Object, currentObservation: Object,
onPressClose: Function, onPressClose: Function,
observations: Array<Object>, observations: Object[],
onDelete?: Function, onDelete?: Function,
updateObservations: Function updateObservations: Function
} }

View File

@@ -15,7 +15,7 @@ const { useRealm } = RealmContext;
type Props = { type Props = {
onPressClose: Function, onPressClose: Function,
discardObservation: Function, discardObservation: Function,
observations: Array<Object>, observations: Object[],
onSave?: Function onSave?: Function
} }

View File

@@ -35,7 +35,7 @@ const AnimatedFlashList = Animated.createAnimatedComponent( CustomFlashList );
type Props = { type Props = {
contentContainerStyle?: Object, contentContainerStyle?: Object,
data: Array<Object>, data: Object[],
dataCanBeFetched?: boolean, dataCanBeFetched?: boolean,
fetchFromLastObservation?: Function, fetchFromLastObservation?: Function,
explore: boolean, explore: boolean,

View File

@@ -7,7 +7,7 @@ import React from "react";
type Props = { type Props = {
item: Object, item: Object,
selectedObservations: Array<Object>, selectedObservations: Object[],
selectObservationPhotos: Function, selectObservationPhotos: Function,
style?: Object style?: Object
} }

View File

@@ -23,11 +23,11 @@ import GroupPhotoImage from "./GroupPhotoImage";
type Props = { type Props = {
combinePhotos: Function, combinePhotos: Function,
groupedPhotos: Array<Object>, groupedPhotos: Object[],
isCreatingObservations?: boolean, isCreatingObservations?: boolean,
navBasedOnUserSettings: Function, navBasedOnUserSettings: Function,
removePhotos: Function, removePhotos: Function,
selectedObservations: Array<Object>, selectedObservations: Object[],
selectObservationPhotos: Function, selectObservationPhotos: Function,
separatePhotos: Function, separatePhotos: Function,
totalPhotos: number totalPhotos: number

View File

@@ -2,7 +2,7 @@
const sortByTime = array => array.sort( ( a, b ) => b.timestamp - a.timestamp ); const sortByTime = array => array.sort( ( a, b ) => b.timestamp - a.timestamp );
const flattenAndOrderSelectedPhotos = ( selectedObservations: ?Array<Object> ): Array<Object> => { const flattenAndOrderSelectedPhotos = ( selectedObservations: ?Object[] ): Object[] => {
// combine selected observations into a single array // combine selected observations into a single array
let combinedPhotos = []; let combinedPhotos = [];
selectedObservations?.forEach( obs => { selectedObservations?.forEach( obs => {

View File

@@ -12,7 +12,7 @@ import {
import ProjectListItem from "./ProjectListItem"; import ProjectListItem from "./ProjectListItem";
interface Props { interface Props {
projects: Array<object>; projects: object[];
ListEmptyComponent?: React.JSX.Element; ListEmptyComponent?: React.JSX.Element;
ListFooterComponent?: React.JSX.Element; ListFooterComponent?: React.JSX.Element;
onEndReached?: ( ) => void; onEndReached?: ( ) => void;

View File

@@ -12,10 +12,10 @@ import changeLanguage from "sharedHelpers/changeLanguage";
import { useTranslation } from "sharedHooks"; import { useTranslation } from "sharedHooks";
import { zustandStorage } from "stores/useStore"; import { zustandStorage } from "stores/useStore";
type LocalesResponse = Array<{ type LocalesResponse = {
locale: string; locale: string;
language_in_locale: string; language_in_locale: string;
}>; }[];
type Props = { type Props = {
onChange: ( newLocale: string ) => void; onChange: ( newLocale: string ) => void;

View File

@@ -23,7 +23,7 @@ interface Props extends PropsWithChildren {
containerClass?: string; containerClass?: string;
onLayout?: () => void; onLayout?: () => void;
sticky?: boolean; sticky?: boolean;
buttonConfiguration?: Array<ButtonConfiguration>; buttonConfiguration?: ButtonConfiguration[];
} }
// Ensure this component is placed outside of scroll views // Ensure this component is placed outside of scroll views

View File

@@ -36,7 +36,7 @@ interface Props {
// Callback when the user presses the close button or backdrop, not whenever the sheet // Callback when the user presses the close button or backdrop, not whenever the sheet
// closes // closes
onPressClose?: ( ) => void; onPressClose?: ( ) => void;
snapPoints?: Array<string>; snapPoints?: string[];
insideModal?: boolean; insideModal?: boolean;
keyboardShouldPersistTaps?: string; keyboardShouldPersistTaps?: string;
testID?: string; testID?: string;

View File

@@ -4,7 +4,7 @@ import { View } from "components/styledComponents";
import React from "react"; import React from "react";
type Props = { type Props = {
iconClasses: Array<string>; iconClasses: string[];
completeColor: string; completeColor: string;
} }

View File

@@ -8,7 +8,7 @@ import { useTranslation } from "sharedHooks";
type Props = { type Props = {
color: string; color: string;
progress: number; progress: number;
iconClasses: Array<string>; iconClasses: string[];
uniqueKey?: string; uniqueKey?: string;
} }

View File

@@ -27,7 +27,7 @@ type Props = {
shouldUseEvidenceLocation: boolean, shouldUseEvidenceLocation: boolean,
onPressPhoto: Function, onPressPhoto: Function,
onTaxonChosen: Function, onTaxonChosen: Function,
photoUris: Array<string>, photoUris: string[],
reloadSuggestions: Function, reloadSuggestions: Function,
selectedPhotoUri: string, selectedPhotoUri: string,
showImproveWithLocationButton: boolean, showImproveWithLocationButton: boolean,

View File

@@ -40,7 +40,7 @@ type Props = {
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
hideLocationToggleButton: Function; hideLocationToggleButton: Function;
hideSkip?: boolean; hideSkip?: boolean;
observers: Array<string>; observers: string[];
shouldUseEvidenceLocation: boolean; shouldUseEvidenceLocation: boolean;
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
toggleLocation: Function; toggleLocation: Function;

View File

@@ -13,7 +13,7 @@ const params = {
}, },
}; };
const useObservers = ( taxonIds: Array<number> ): Array<string> => { const useObservers = ( taxonIds: number[] ): string[] => {
const { data } = useAuthenticatedQuery( const { data } = useAuthenticatedQuery(
["fetchObservers", taxonIds], ["fetchObservers", taxonIds],
( ) => fetchObservers( { ( ) => fetchObservers( {

View File

@@ -20,13 +20,13 @@ import Photo from "realmModels/Photo";
type Props = { type Props = {
loading: boolean, loading: boolean,
onChangeIndex?: Function, onChangeIndex?: Function,
photos: Array<{ photos: {
id?: number, id?: number,
url: string, url: string,
localFilePath?: string, localFilePath?: string,
attribution?: string, attribution?: string,
licenseCode?: string licenseCode?: string
}>, }[],
tablet: boolean tablet: boolean
} }

View File

@@ -18,7 +18,7 @@ interface Props {
ListFooterComponent?: React.JSX.Element; ListFooterComponent?: React.JSX.Element;
onEndReached?: ( ) => void; onEndReached?: ( ) => void;
refreshing?: boolean; refreshing?: boolean;
users: Array<object>; users: object[];
onPress?: ( ) => void; onPress?: ( ) => void;
accessibilityLabel?: string; accessibilityLabel?: string;
keyboardShouldPersistTaps?: string; keyboardShouldPersistTaps?: string;

View File

@@ -16,7 +16,7 @@ const DROP_SHADOW = getShadow( {
} ); } );
type Props = { type Props = {
tabs: Array<Object>, tabs: Object[],
}; };
/* eslint-disable react/jsx-props-no-spreading */ /* eslint-disable react/jsx-props-no-spreading */

View File

@@ -161,10 +161,10 @@ interface PLACE {
id: number; id: number;
place_type: number; place_type: number;
point_geojson: { point_geojson: {
coordinates: Array<number>; coordinates: number[];
}; };
bounding_box_geojson?: { bounding_box_geojson?: {
coordinates: Array<number>; coordinates: number[];
}; };
type: string; type: string;
} }

View File

@@ -106,18 +106,18 @@ export interface RealmObservationPojo {
_created_at?: Date; _created_at?: Date;
_synced_at?: Date; _synced_at?: Date;
captive_flag: boolean | null; captive_flag: boolean | null;
comments: Array<RealmComment>; comments: RealmComment[];
comments_viewed?: boolean; comments_viewed?: boolean;
description: string | null; description: string | null;
geoprivacy: string | null; geoprivacy: string | null;
identifications: Array<RealmIdentification>; identifications: RealmIdentification[];
identifications_viewed?: boolean; identifications_viewed?: boolean;
latitude: number | null; latitude: number | null;
license_code: License | null; license_code: License | null;
longitude: number | null; longitude: number | null;
obscured?: boolean; obscured?: boolean;
observationPhotos: Array<RealmObservationPhotoPojo>; observationPhotos: RealmObservationPhotoPojo[];
observationSounds: Array<RealmObservationSoundPojo>; observationSounds: RealmObservationSoundPojo[];
observed_on?: string; observed_on?: string;
observed_on_string: string | null; observed_on_string: string | null;
observed_time_zone?: string; observed_time_zone?: string;
@@ -139,8 +139,8 @@ export interface RealmObservationPojo {
export interface RealmObservation extends RealmObservationPojo { export interface RealmObservation extends RealmObservationPojo {
missingBasics: ( ) => boolean; missingBasics: ( ) => boolean;
needsSync: ( ) => boolean; needsSync: ( ) => boolean;
observationPhotos: Array<RealmObservationPhoto>; observationPhotos: RealmObservationPhoto[];
observationSounds: Array<RealmObservationSound>; observationSounds: RealmObservationSound[];
unviewed: ( ) => boolean; unviewed: ( ) => boolean;
updateNeedsSync: ( ) => boolean; updateNeedsSync: ( ) => boolean;
viewed: ( ) => boolean; viewed: ( ) => boolean;

View File

@@ -5,24 +5,24 @@ class FlashListPerformanceTracker {
private itemsVisibleDuration: number; private itemsVisibleDuration: number;
private scrollEvents: Array<{ private scrollEvents: {
startTime: number; startTime: number;
endTime: number; endTime: number;
duration: number; duration: number;
itemsFetched: number; itemsFetched: number;
scrollDistance: number; scrollDistance: number;
}> = []; }[] = [];
private currentScrollEvent: unknown = null; private currentScrollEvent: unknown = null;
private fetchStartTime: number; private fetchStartTime: number;
private fetchEvents: Array<{ private fetchEvents: {
startTime: number; startTime: number;
endTime: number; endTime: number;
duration: number; duration: number;
itemsCount: number; itemsCount: number;
}> = []; }[] = [];
private persistentMetrics = { private persistentMetrics = {
lastFetchTime: null as number | null, lastFetchTime: null as number | null,

View File

@@ -63,11 +63,11 @@ export const formatExifDateAsString = ( datetime: string ): string => {
// Parse the EXIF of all photos - fill out details (lat/lng/date) from all of these, // Parse the EXIF of all photos - fill out details (lat/lng/date) from all of these,
// in case the first photo is missing EXIF // in case the first photo is missing EXIF
export const readExifFromMultiplePhotos = async ( photoUris: Array<string> ): Promise<Object> => { export const readExifFromMultiplePhotos = async ( photoUris: string[] ): Promise<Object> => {
const unifiedExif = {}; const unifiedExif = {};
const responses = await Promise.allSettled( photoUris.map( parseExif ) ); const responses = await Promise.allSettled( photoUris.map( parseExif ) );
const allExifPhotos: Array<{ const allExifPhotos: {
latitude: number, latitude: number,
longitude: number, longitude: number,
positional_accuracy: number, positional_accuracy: number,
@@ -75,7 +75,7 @@ export const readExifFromMultiplePhotos = async ( photoUris: Array<string> ): Pr
// Flow will complain that value is undefined, but the filter call ensures // Flow will complain that value is undefined, but the filter call ensures
// that it isn't // that it isn't
// $FlowIgnore // $FlowIgnore
}> = responses.filter( r => r.value ).map( r => r.value ); }[] = responses.filter( r => r.value ).map( r => r.value );
allExifPhotos.filter( x => x ).forEach( allExifPhotos.filter( x => x ).forEach(
currentPhotoExif => { currentPhotoExif => {

View File

@@ -8,7 +8,7 @@ import { useCurrentUser } from "sharedHooks";
// Should work like React Query's useInfiniteQuery with our custom reactQueryRetry // Should work like React Query's useInfiniteQuery with our custom reactQueryRetry
// and authentication // and authentication
const useAuthenticatedInfiniteQuery = ( const useAuthenticatedInfiniteQuery = (
queryKey: Array<string>, queryKey: string[],
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
queryFunction: Function, queryFunction: Function,
queryOptions: object = {}, queryOptions: object = {},

View File

@@ -5,7 +5,7 @@ const useInfiniteUserScroll = (
queryKey: string, queryKey: string,
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
apiCall: Function, apiCall: Function,
ids: Array<object>, ids: object[],
newInputParams: object, newInputParams: object,
options: { options: {
enabled: boolean; enabled: boolean;

View File

@@ -4,7 +4,7 @@ import { handleRetryDelay, reactQueryRetry } from "sharedHelpers/logging";
// Should work like React Query's useQuery with our custom reactQueryRetry // Should work like React Query's useQuery with our custom reactQueryRetry
const useNonAuthenticatedQuery = ( const useNonAuthenticatedQuery = (
queryKey: Array<string>, queryKey: string[],
queryFunction: QueryFunction, queryFunction: QueryFunction,
queryOptions: object = {}, queryOptions: object = {},
) => useQuery( { ) => useQuery( {

View File

@@ -16,7 +16,7 @@ interface SyncObservationsSlice {
autoSyncAbortController: AbortController | null; autoSyncAbortController: AbortController | null;
currentDeleteCount: number; currentDeleteCount: number;
deleteError: string | null; deleteError: string | null;
deleteQueue: Array<string>; deleteQueue: string[];
deletionsCompletedAt: Date | null; deletionsCompletedAt: Date | null;
initialNumDeletionsInQueue: number; initialNumDeletionsInQueue: number;
syncingStatus: SyncingStatus; syncingStatus: SyncingStatus;

View File

@@ -30,8 +30,8 @@ interface UploadObservationsSlice {
numUploadsAttempted: number; numUploadsAttempted: number;
totalToolbarIncrements: number; totalToolbarIncrements: number;
totalToolbarProgress: number; totalToolbarProgress: number;
totalUploadProgress: Array<TotalUploadProgress>; totalUploadProgress: TotalUploadProgress[];
uploadQueue: Array<string>; uploadQueue: string[];
uploadStatus: UploadStatus; uploadStatus: UploadStatus;
} }

View File

@@ -22,9 +22,9 @@ interface MediaApiResponse {
page: number; page: number;
per_page: number; per_page: number;
total_results: number; total_results: number;
results: Array<{ results: {
id: number; id: number;
}>; }[];
} }
interface MappedObservationPhotoForUpdating { interface MappedObservationPhotoForUpdating {

View File

@@ -38,10 +38,10 @@ interface ObservationApiResponse {
page: number; page: number;
per_page: number; per_page: number;
total_results: number; total_results: number;
results: Array<{ results: {
uuid: string; uuid: string;
id: number; id: number;
}>; }[];
} }
async function validateAndGetToken( ): Promise<string> { async function validateAndGetToken( ): Promise<string> {

View File

@@ -84,7 +84,7 @@ const markRecordUploaded = (
recordUUID: string | null, recordUUID: string | null,
type: string, type: string,
response: { response: {
results: Array<{id: number}>; results: {id: number}[];
}, },
realm: object, realm: object,
options?: { options?: {