简体   繁体   中英

use reduce in typescript, Error "element implicitly has an 'any' type because expression of type can't be used to index type '{}'"

I get error:

element implicitly has an 'any' type because expression of type 'POST_TYPE' can't be used to index type '{}' Property '[POST_TYPE.POST]' does not exist on type '{}';

error when using reduce on a function with an interface like this:

// enum
export const enum POST_TYPE {
  POST = 'POST',
  BOARD = 'BOARD',
  ...
}

// interface
export interface Post {
  postType?: POST_TYPE[];
}

export interface PostType {
  POST?: boolean;
  BOARD?: boolean;
}

// function
const exec = (prevType: Post['postType'], type: PostType) => {
 const prevObject = prevType.reduce((prev, it) => {
    prev[it] = true; -->> ERROR in prev[it]
    return prev;
  }, {});
}

What mistake did I make?

One issue is that your argument prevType: Post['postType'] may be undefined , because Post['postType'] may be undefined . Not sure what you're trying to do there, but perhaps make the postType property required on Post , and type-check before passing the object to exec .

In your code, the second parameter passed to reduce lacks a type - it's just a plain object, and you didn't pass a type parameter to .reduce , so Typescript won't allow you to add arbitrary key-value pairs to it.

If you pass a type parameter to reduce , this will denote the type of the initial value and the accumulator. Here, because the type will be an object with partial properties of POST_TYPE , create such an object type and use Partial . Then you can assert that the return value is a full object (without missing properties):

export interface Post {
    postType: POST_TYPE[];
}
const exec = (prevType: Post['postType']) => {
    type PostObj = {
        [T in POST_TYPE]: boolean;
    };
    const prevObject = prevType.reduce<Partial<PostObj>>((prev, it) => {
        prev[it] = true;
        return prev;
    }, {}) as PostObj;
};

But reduce is a bit verbose and arguably not the right tool to use when creating a single object anyway. It might be more appropriate to just declare the object and assign to its properties, or to use Object.fromEntries :

const postObj = Object.fromEntries(
    prevType.map(it => [it, true])
) as PostObj;

(unfortunately, TS doesn't look to be able to infer the type of the return value of fromEntries sufficiently yet, thus the need for the type assertion)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM