1
import React, { useState } from 'react';

interface PropsInterface {
  keys: string; // name,email,password
}

const Poster: React.FC<PropsInterface> = (props: PropsInterface) => {

  const [state, setState] = useState({
    name: 'jim',
    email: '[email protected]',
    password: 'secret',
    loading: false,
    keys: props.keys.split(','),  // [ name, email, password ]
  });
  const { keys } = state;

I need to somehow get the values for each of the keys and form a string that will end up looking like this

"name=jim&[email protected]&password=secret"

I thought I could simply use URLSearchParams() that quickly became a problem with TypeScript. My next thought was to loop over the keys and then get the corresponding values from the state

    for (const i in keys) {
      if (keys.hasOwnProperty(i)) {
        console.log(state[keys[i]]);
      }
    }

which then gives me the error

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ auth: boolean; baseUrl: string; keys: string[]; method: string; }'.
  No index signature with a parameter of type 'string' was found on type '{ auth: boolean; baseUrl: string; keys: string[]; method: string; }'.ts(7053)
4
  • Is the type it's complaining about the type of your state? (It has property names your state doesn't have, but I wonder if you've cut your state down for the purposes of the question...) Commented Jan 30, 2020 at 13:55
  • yes I simplified it to make it easy to read Commented Jan 30, 2020 at 13:56
  • Fundamentally, when you do state[keys[i]], you're using a string to index into state. If your state object's type doesn't have an index signature, TypeScript won't let you do that (without a type assertion)... Commented Jan 30, 2020 at 13:56
  • ok, how to make an assertion that will make TypeScript happy about this? Commented Jan 30, 2020 at 13:57

2 Answers 2

3

Fundamentally, when you do state[keys[i]], you're using a string to index into state. If your state object's type doesn't have an index signature, TypeScript won't let you do that (without a type assertion)...

You can use a local type assertion, perhaps with an alias variable, instead:

const rawState = state as any as Record<string, string>;
for (const key of keys) {
    console.log(rawState[key]);
}

(Also note using for-of to loop the array.)

Of course, that's disabling type checking for that loop...

Live on the playground

Sign up to request clarification or add additional context in comments.

Comments

0

As I understand, it's maybe your solution to solve the problem.

import * as React from "react";
import { render } from "react-dom";

interface PropsInterface {
  keys: string; // name,email,password
}

const Poster: React.FC<PropsInterface> = (props: PropsInterface) => {
  const [state, setState] = React.useState({
    name: 'jim',
    email: '[email protected]',
    password: 'secret',
    loading: false,
    keys: props.keys.split(','),  // [ name, email, password ]
  });
  const pairKeys = React.useMemo<string>(() => {
    const order = ["name", "email", "password"];
    const result: string[] = [];

    state.keys.forEach((key: string, index) => {
      result.push(`${order[index]}=${state[order[index]]}`)
    });

    return result.join("&")
  }, [state.keys])

  return (
    <div>{JSON.stringify(pairKeys, null, 2)}</div>
  )
}



render(<Poster keys="John,[email protected],testpass" />, document.getElementById("root"));

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.