Home > OS >  Get local JSON data: The element has a type "any" implicitly
Get local JSON data: The element has a type "any" implicitly

Time:11-14

I have a project in Node JS with Typescript in which I am creating an API to get data from a local JSON file depending on the given variable.

This is my model.ts:

interface ListProductBatchModel {
    resp: ResultMsg
}

interface ResultMsg {
    name?: string,
    price?: string,
    error?: string
}

export { ListProductBatchModel, ResultMsg };

This is my properties JSON file:

{
    "CT": {
        "name": "box",
        "price": "5,00"
    },
    "CC": {
        "name": "car",
        "price": "6,00"
    }
}

This is my controller.ts:

import * as logger from 'winston';
import { Controller, Get, Response, Route, SuccessResponse, Tags } from 'tsoa';

import { ListProductBatchModel } from './models/listProduct.models';
import { ListProductBatchUtils } from './utils/listProductBatch.utils';

@Route('/list/product')
@Tags('list-product')

export class ListProductBatchController {

    private listProductBatchUtils: ListProductBatchUtils;

    constructor() {
        this.listProductBatchUtils = new ListProductBatchUtils();
    }

    @Get('/{codProduct}')
    @SuccessResponse(200, 'Success Response')
    async listProductBatch(codProduct: string): Promise<ListProductBatchModel> {
        try {
            const listProductBatch = await this.listProductBatchUtils.getDataProduct(codProduct);
            return Promise.resolve(listProductBatch as ListProductBatchModel);
        } catch (error) {
            logger.info(JSON.stringify(error));
            return Promise.reject(error);
        }
    }
}

This is my utils.ts:

import * as logger from 'winston';
import * as getProperty from '../json/product.json';
import { ListProductBatchModel, ResultMsg } from '../models/listProduct.models';

export class ListProductBatchUtils {

    public async getDataProduct(codProduct: string): Promise<ListProductBatchModel> {

        try {

            let result: ResultMsg;
            if (getProperty[codProduct.toUpperCase()]) {
                result = {
                    name: getProperty[codProduct.toUpperCase()].name,
                    price: getProperty[codProduct.toUpperCase()].price
                }

            }else {
                result = {
                    error: "ERROR"
                }
            }
            logger.info('start')
            return Promise.resolve({ resp: result });
            
        } catch (error) {
            logger.info(JSON.stringify(error));
            return Promise.reject(error);
        }
    }
}

This is the error I get in getProperty [codProduct.toUpperCase ()]:

The element has a type "any" implicitly because the expression of type "string" cannot be used to index the type "{CT: {name: string; price: string;}; CC: {name: string; price : string;};} ".
   No index signature was found with a parameter of type "string" in type "{CT: {name: string; price: string;}; CC: {name: string; price: string;};}".

My problem: I don't understand how the error is generated, what I want is to take the name and price properties that match the codProduct variable. Why can this happen? What am I doing wrong and how can I solve it?

CodePudding user response:

Right now, codProduct is a string. When you're accessing getProduct via its subscript [], TypeScript expects you to use an index of getProduct (which, in this case is either "CT" or "CC").

You can satisfy the TypeScript compiler by casting your string as a keyof getProperty's type. Note that this will work at compile time, but will not guarantee that it is in fact a key of getProperty at runtime. But, since you're doing boolean checks already, that seems like it will be okay in your case.

Here's a simplified example:

const getProperty = {
    "CT": {
        "name": "box",
        "price": "5,00"
    },
    "CC": {
        "name": "car",
        "price": "6,00"
    }
};

type GetPropertyType = typeof getProperty;

function myFunc(input: string) {
    const result = getProperty[input.toUpperCase() as keyof GetPropertyType].name;
}
  • Related