Cómo (propiamente) escribir un formulario con tipografía (y no bibliotecas externas)
Estoy tratando de crear una forma sencilla y estoy luchando para decirle a Typescript qué valores me gustaría tener mis entradas. Hasta ahora lo que he visto al buscar una respuesta son un montón de bibliotecas y hooks hechos a medida que manejan todo bajo la capucha, pero nada que lo haría sin la ayuda de bibliotecas externas. Espero que alguien por aquí tenga una sugerencia.
Quiero tener un formulario básico de austeridad donde estoy recibiendo el nombre de usuario, correo electrónico y contraseña de los usuarios. Como necesito decirle a Typescript que estoy esperando desde el onChange
callback sólo un cierto conjunto de llaves, he extendido HTMLInputElement
en mi tipo personalizado. Sin embargo esto parece no ser un enfoque correcto, ya que entonces no soy capaz de proporcionar mi onChange
manipulador a los respectivos input
de la forma. ¿Alguien sabe cómo Tipo apropiado (sin as <>
as unknown as <>
o bibliotecas específicas) una forma de este tipo? ¡Gracias!
Mi código:
interface ISignUpState {
username: string;
email: string;
passwordOne: string;
passwordTwo: string;
error: string;
}
interface InputProps extends InputHTMLAttributes {
name: keyof ISignUpState;
value: ISignUpState[InputProps["name"]]
}
const INITIAL_STATE: ISignUpState = {
username: '',
email: '',
passwordOne: '',
passwordTwo: '',
error: ''
}
export const SignUpForm = () => {
const [state, setState] = React.useState(INITIAL_STATE);
const onSubmit = (event: React.FormEvent) => {
}
const onChange = (event:React.ChangeEvent) => {
setState(prevState => ({...prevState, [event.target.name]: event.target.value}))
}
const {username, email, passwordOne, passwordTwo, error} = state;
return (
)
}
Y Typescript se queja de onChange
:
Type '(event: React.ChangeEvent) => void' is not assignable to type '(event: ChangeEvent) => void'.
Types of parameters 'event' and 'event' are incompatible.
Type 'ChangeEvent' is not assignable to type 'ChangeEvent'.
Type 'HTMLInputElement' is not assignable to type 'InputProps'.
Types of property 'name' are incompatible.
Type 'string' is not assignable to type '"username" | "email" | "passwordOne" | "passwordTwo" | "error"'.
Pregunta hecha hace 3 años, 4 meses, 27 días - Por binaryblossom
3 Respuestas:
-
TipoScript no integra el tipo de
name
prop en el valor aevent.target.name
- todo lo que se puede decir es que tal valor es unstring
, que no se puede utilizar donde una claveISignUpState
se espera (que es más estrecho). Así que...React.ChangeEvent
no es usable - tendrá que usarChangeEvent
, como TS dice que es necesario.const onChange = (event: React.ChangeEvent
) => { setState(prevState => ({ ...prevState, [event.target.name]: event.target.value })); }; Podrías pensar que el
event.target.name
allí, escrito como una String, es raro, ya que no se escribe como una llaveISignUpState
- pero TypeScript lo acepta.Si TipoScript no aceptarlo, usted podría utilizar un tipo de aserción o estrechar el tipo antes de combinar el objeto (quizá inicie un error si el estrechamiento de tipo falla) - pero no es necesario.
Respondida el Dec 18, 2020 a las 19:39 - por stackscripter
Votos positivos: 0 | Votos negativos: 0 -
El problema que estás experimentando es debido a que estás definiendo mal la interfaz
InputProps
al extenderInputHTMLAttributes<htmlinputelement>
. Para corregirlo, puedes definirInputProps
de la siguiente manera:typescript interface InputProps { name: keyof ISignUpState; value: ISignUpState[keyof ISignUpState]; onChange: (event: React.ChangeEvent
) => void; } Luego, puedes modificar tu función
onChange
para que cumpla con la firma correcta del evento:typescript const onChange = (event: React.ChangeEvent
) => { setState(prevState => ({...prevState, [event.target.name]: event.target.value})) } Y finalmente, puedes asignar correctamente el
onChange
a tu input en el formulario:typescript return ( )
Con estas correcciones, el error que estás experimentando debe resolverse y tu formulario debería funcionar correctamente sin necesidad de bibliotecas externas.
Respondida el Dec 19, 2020 a las 19:41 - por Gpt
Votos positivos: 0 | Votos negativos: 0 -
El problema con tu código es que intentas extender la interfaz
HTMLInputElement
con tu interfaz personalizadaInputProps
. Esto no es posible porqueHTMLInputElement
es una interfaz nativa de JavaScript y no se puede extender con interfaces personalizadas.Para solucionar este problema, puedes crear una interfaz personalizada que extienda
ChangeEvent<HTMLInputElement>
y agregue las propiedades adicionales que necesitas:typescript interface InputChangeEvent extends ChangeEvent
{ target: InputProps; } Luego, puedes usar esta interfaz personalizada para escribir tu función
onChange
:typescript const onChange = (event: InputChangeEvent) => { setState(prevState => ({...prevState, [event.target.name]: event.target.value})) }
Esto le dirá a TypeScript que la función
onChange
espera un evento que tenga un objetivo que sea una instancia de la interfazInputProps
. Esto asegurará que solo se pasen eventos válidos a la funciónonChange
.Además, en tu código HTML, debes usar la interfaz
InputProps
para escribir las propiedades de los elementos de entrada:html
Esto le dirá a TypeScript que los elementos de entrada tienen propiedades que coinciden con la interfaz
InputProps
.Una vez que hayas realizado estos cambios, TypeScript ya no debería quejarse de los tipos de la función
onChange
.Respondida el Dec 19, 2020 a las 19:42 - por Gemini
Votos positivos: 0 | Votos negativos: 0