【问题标题】:Nested Object -> Element implicitly has an 'any' type because expression of type 'string' can't be used to index type嵌套对象 -> 元素隐式具有“任何”类型,因为“字符串”类型的表达式不能用于索引类型
【发布时间】:2020-08-24 18:09:07
【问题描述】:

我有一个反应表单组件,我正在尝试将其重写为打字稿。我正在尝试在 for 循环中检索另一个对象中的一个对象,但我不断收到以下错误

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 

我尝试了以下问题中提出的解决方案,但我仍然无法找到有效的解决方案,并且我不希望在 tsconfig.json 中将 noImplicitAny 设置为 false

  1. TypeScript: Object.keys return string[]

  2. TypeScript TS7015: Element implicitly has an 'any' type because index expression is not of type 'number'

  3. element implicitly has an 'any' type because type '{0}' has no index signature.

有问题的代码是 - 有问题的区域可以在底部附近找到:

import React from 'react';

import Button from '../../UI/Button/Button';
import Input from '../../UI/Input/Input';


type Config = {
    elementType: string;
    elementConfig: {
        type: string;
        placeholder: string;
        options: {
            value: string;
            displayValue: string;
        };
    };
    value: string;
    validation: {
        required: boolean;
        isEmail?: boolean;
        minLength?: number;
    };
    valid: boolean;
    touched: boolean;
    fieldActive: boolean;
    // [key: string]: string | Object;
}

interface SignInFormProps {
    isSignIn: boolean;
}

interface SignInFormState {
    controls: {
        email: Config;
        password: Config;
    };
    isSignUp: boolean;
    [key: string]: boolean | Object | Config;
}


class SignInForm extends React.Component<SignInFormProps, SignInFormState> {
    state = {
        controls: {
            email: {
                elementType: 'input',
                elementConfig: {
                    type: 'email',
                    placeholder: 'Your Email',
                    options: {
                        value: '',
                        displayValue: ''
                    },
                },
                value: '',
                validation: {
                    required: true,
                    isEmail: true
                },
                valid: false,
                touched: false,
                fieldActive: false
            },
            password: {
                elementType: 'input',
                elementConfig: {
                    type: 'password',
                    placeholder: 'Password',
                    options: {
                        value: '',
                        displayValue: ''
                    },
                },
                value: '',
                validation: {
                    required: true,
                    minLength: 6
                },
                valid: false,
                touched: false,
                fieldActive: false
            }
        },
        isSignUp: true
    }

    private activateField = ( controlName: keyof SignInFormState['controls'] ) => {
        do stuff...
    }

    ...

    render() {
        const formElementsArray: {id: string, config: Config}[] = [];

        // ################ The config value is causing the error ################
        for ( let key in this.state.controls ) {
            formElementsArray.push({
                id: key,
                config: this.state.controls[key] as Config
            });
        }

        let form = formElementsArray.map( formElement => (
            <Input
                blur={ ( event ) => this.disableFocus(event, formElement.id) }
                changed={ ( event ) => this.inputChangedHandler(event, formElement.id) }
                elementConfig={formElement.config.elementConfig}
                elementType={formElement.config.elementType}
                fieldActive={formElement.config.fieldActive}
                focus={ () => this.activateField(formElement.id) }
                invalid={!formElement.config.valid}
                key={formElement.id}
                shouldValidate={formElement.config.validation.required}
                touched={formElement.config.touched}
                value={formElement.config.value} />
        ));

如果有人对如何在明确定义类型且不使用任何类型的情况下解决此问题有任何想法,那将很有帮助。

【问题讨论】:

    标签: reactjs typescript


    【解决方案1】:

    首先,没有一个很好的方法可以做到这一点,它仍在讨论中:https://github.com/Microsoft/TypeScript/issues/3500

    以下是解决问题的 2 种潜在方法。

    1. 在循环外声明键:
    const formElementsArray: { id: string; config: Config }[] = [];
    let key: keyof typeof this.state.controls;
    for (key in this.state.controls) {
      formElementsArray.push({
        id: key,
        config: this.state.controls[key],
      });
    }
    
    1. 使用 Object.keys 并将密钥转换为所需的类型:
    const formElementsArray: { id: string; config: Config }[] = (Object.keys(
      this.state.controls
    ) as (keyof typeof this.state.controls)[]).map((key) => ({
      id: key,
      config: this.state.controls[key],
    }));
    

    您还可以通过使用控制键的枚举来使其更清晰

    enum ControlKey {
      email = "email",
      password = "password",
    }
    
    interface SignInFormState {
      controls: {
        [key in ControlKey]: Config;
      };
      isSignUp: boolean;
      [key: string]: boolean | Object | Config;
    }
    

    然后

    1b.

    const formElementsArray: { id: string; config: Config }[] = [];
    let key: ControlKey;
    for (key in this.state.controls) {
      formElementsArray.push({
        id: key,
        config: this.state.controls[key],
      });
    }
    

    2b.

    const formElementsArray: { id: string; config: Config }[] = (Object.keys(
      this.state.controls
    ) as ControlKey[]).map((key) => ({
      id: key,
      config: this.state.controls[key],
    }));
    

    希望对你有帮助

    【讨论】:

      猜你喜欢
      • 2021-08-08
      • 1970-01-01
      • 2021-03-17
      • 2021-04-20
      • 1970-01-01
      • 2020-11-13
      • 2019-12-17
      • 2020-10-29
      • 2020-10-04
      相关资源
      最近更新 更多