Вложенный объект -> Элемент неявно имеет тип 'любой', поскольку выражение типа 'строка' не может использоваться для индексации типа - PullRequest
0 голосов
/ 09 мая 2020

У меня есть компонент формы реакции, который я пытаюсь переписать в машинописный текст. Я пытаюсь получить объект в другом объекте в for l oop, но все равно получаю следующую ошибку:

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

Я попытался найти решение, представленное в следующих вопросах, но все равно не смог есть рабочее решение, и я не могу sh устанавливать noImplicitAny в false в tsconfig.json:

  1. TypeScript: Object.keys return string []

  2. TypeScript TS7015: элемент неявно имеет тип «любой», поскольку выражение индекса не относится к типу «число»

  3. элемент неявно имеет тип 'any', потому что тип '{0}' не имеет подписи индекса .

Рассматриваемый код - Проблема Область c находится внизу:

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} />
        ));

Если у кого-нибудь есть идеи о том, как решить эту проблему, имея четко определенные типы и не используя их, то это будет полезно.

1 Ответ

1 голос
/ 09 мая 2020

Прежде всего, это не лучший способ сделать это, и он все еще обсуждается: https://github.com/Microsoft/TypeScript/issues/3500

Ниже приведены 2 возможных способа решения вашей проблемы.

  1. Объявить ключ вне l oop:
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],
  });
}
Используйте 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],
}));

Надеюсь, это поможет

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...