类型不满足约束。类型中缺少索引签名

时间:2019-09-16 17:32:23

标签: javascript reactjs typescript react-hooks typescript-typings

我正在为使用打字稿并使用React Hooks编写的项目制作refacto。我虽然不是专家,但更像是初学者,因此对打字稿有一些了解。

我正在尝试为该项目开发一些代码重用(这就是为什么使用钩子进行refacto的原因),并且我陷入了一个简单的错误中,我当然可以找到一个窍门,但是我想发现为什么它不起作用

我有一个简单的登录表单,其中包含2个输入(电子邮件和密码):

LoginForm

import React from 'react';
import { SmartInput, RoundButton } from '@/components';
import { useMultipleInputs } from '@/hooks';

interface ILoginFormProps {
    onLogin: (email: string, password: string) => Promise<void>;
    errorMsg?: string;
}

interface ILoginFormInputs {
    password: string;
    email: string;
}

export const LoginForm = ({
    onLogin,
    errorMsg,
}: ILoginFormProps): JSX.Element => {
    const [inputs, setInputs] = useMultipleInputs<ILoginFormInputs>(); // line where the error occur

    const onSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
        const { email, password } = inputs;
        e.preventDefault();
        await onLogin(email, password);
    };

    const displayErrorMsg = () => {
        if (errorMsg) {
            return (
                <p className='body-text body-text--medium body-text--error auth-form__form__error-msg'>
                    {errorMsg}
                </p>
            );
        }
        return null;
    };

    return (
        <div className='auth-form'>
            <div className='auth-form__container'>
                <div className='auth-form__container__title title title--big'>
                    Sign in to <br />
                    Esport-Hatcher
                </div>
                <form className='auth-form__basic' onSubmit={onSubmit}>
                    <SmartInput
                        type='email'
                        placeholder='Email'
                        name='email'
                        icon='mail'
                        value={inputs.email}
                        onChange={setInputs}
                    />
                    <SmartInput
                        type='password'
                        placeholder='Password'
                        name='password'
                        icon='lock'
                        value={inputs.password}
                        onChange={setInputs}
                    />
                    {displayErrorMsg()}
                    <RoundButton onClick={() => null} />
                </form>
            </div>
        </div>
    );
};

我想将输入的状态延迟到自定义钩子,因此它是可重用的。

useMultipleInputs

import React, { useState } from 'react';

interface IInputs {
    [key: string]: string;
}

export const useMultipleInputs = <T extends IInputs>(): [
    T,
    typeof onChange
] => {
    const [inputs, setInputs] = useState<T | {}>({});

    const onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
        setInputs({
            ...inputs,
            [e.target.name]: e.target.value,
        });
    };
    return [inputs as T, onChange];
};

可悲的是,正如您在第一个屏幕截图中看到的那样,我得到一个错误:

Type 'ILoginFormInputs' does not satisfy the constraint 'IInputs'.

Index signature is missing in type 'ILoginFormInputs'.

打字稿不会将{ email: string, password: string }视为[key: string]: string]吗?

非常感谢您阅读我的文章:)

1 个答案:

答案 0 :(得分:0)

我认为这是设计使然。您可以有多个具有相同名称的接口声明,它们将合并-但您不能对类型进行声明。 (T是不是接口的类型)。因此,TS只是试图在这里变得非常安全。

您可以尝试将ILoginFormInputs的定义更改为更严格的type

type ILoginFormInputs = {
    password: string;
    email: string;
}