I am doing a proyect on React Native and Typescript, I am new on them and I had been having an issue lately that I couldn't solve yet. I am trying to do a login on the app and Typescript keeps giving me errors on a useReducer I did. Unfortunately, i am new with Typescript so in order to solve previous errors I just put any on most of the types. This is the code, it is the input from the login screen:
import React, { useEffect, useReducer } from "react";
import { StyleSheet, Text, TextInput, View } from "react-native";
interface InputComponentProps {
INPUT_CHANGE: any
INPUT_BLUR: any
handleBlur: any
}
const INPUT_CHANGE: any = 'INPUT_CHANGE';
const INPUT_BLUR: any = 'INPUT_BLUR';
const inputReducer: any = (state: any, action: any) => {
switch(action.type) {
case INPUT_CHANGE:
return {
...state,
value: action.value,
isValid: action.isValid,
};
case INPUT_BLUR:
return {
...state,
touched: true,
};
default:
return state;
}
};
const InputComponent: React.FC<InputComponentProps> = (props: any) => {
const [inputState, inputDispatch] = useReducer<any>(inputReducer, {
value: '',
isValid: false,
touched: false,
});
const { onInputChange, id } = props;
useEffect((): (() => void) => {
return onInputChange(id, inputState.value, inputState.isValid);
}, [onInputChange, id, inputState])
const handleChangeText = (text: { trim: () => { (): any; new(): any; length: number; }; toLowerCase: () => string; length: number; }) => {
const emailRegex = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
let isValid = true;
if (props.required && text.trim().length === 0) isValid = false;
if (props.email && !emailRegex.test(text.toLowerCase())) isValid = false;
if (props.minLength && text.length < props.minLength) isValid = false;
inputDispatch({
type: INPUT_CHANGE,
value: text,
isValid: isValid,
});
}
const handleBlur = () => inputDispatch({ type: INPUT_BLUR });
return (
<>
<View style={styles.formControl}>
<Text style={styles.label}>{props.label}</Text>
<TextInput
{...props}
style={styles.input}
value={inputState.value}
onChangeText={handleChangeText}
onBlur={handleBlur}
/>
{!inputState.isValid && inputState.touched && (
<View>
<Text style={styles.errorText}>{props.errorText}</Text>
</View>
)}
</View>
</>
);
}
const styles = StyleSheet.create({
formControl: {
width: '100%',
},
label: {
fontFamily: 'OpenSansBold',
marginVertical: 8,
},
input: {
paddingHorizontal: 2,
paddingVertical: 5,
borderBottomColor: '#ccc',
borderBottomWidth: 1,
},
errorText: {
marginVertical: 5,
color: '#cc7755'
}
});
export default InputComponent;
This is a screenshot of the errors:
If there is someone that could help me, I would really appreciate it!
You have a few too many explicit any
s where you would be better off letting TypeScript infer the type. Specifically, the ones which are causing you trouble are these two:
const inputReducer: any = (
useReducer<any>(
A reducer must be a function that takes a state and an action and returns the next state. By putting any
in these two places, you are telling TypeScript that your reducer is anything and is not necessarily a function.
But it is a function. If you drop those two any
s, then the type which is inferred as the value of inputReducer
and the generic on useReducer
is (state: any, action: any) => any
. This is much more descriptive than just any
. We know that it's a function and that it takes the correct amount of arguments.
When you add vague types where they aren't needed, you are making your code much less type-safe then with no type annotations at all. When you do this:
const INPUT_CHANGE: any = 'INPUT_CHANGE';
You are overriding all of TypeScript's power to infer the correct type. There is no need to put a type when you are assigning a variable because TypeScript will infer that the type of the variable is the same as the type of the value that you assigned.
const INPUT_CHANGE = 'INPUT_CHANGE';
Here, the type of the INPUT_CHANGE
variable is the literal string "INPUT_CHANGE"
instead of any
.