0

So I have a timezone list and has a type of the following:

type TimezoneListType = {
   label: string;
   name: string;
   offset: number;
   lower?: string;
   offsetString?: string;
 };

const TIMEZONE_LIST: TimezoneListType[] = [
  {
    label: 'Niue',
    name: 'Pacific/Niue',
    offset: -11,
  },
  {
    label: 'Pago Pago',
    name: 'Pacific/Pago_Pago',
    offset: -11,
  },
  //... and so on
];

const TIMEZONE_NAME_MAP: any = {};

const TIMEZONE_MAP = TIMEZONE_LIST.map((item) => {
  const positive = item.offset >= 0;
  const hour = item.offset | 0;
  const minute = (item.offset - hour) * 60;
  return TIMEZONE_NAME_MAP[item.name] = {  // typescript is screaming in this line. if try to change the `any` to `TimezoneListType`
    ...item,
    lower: item.label.toLowerCase(),
    offsetString: 'something',
  };
});

on the lower end of the code you'll see that I'm transforming timezone list to have keys of item.name then adding some property lower and offsetString.

My problem is item.name is giving me:

Element implicitly has an 'any' type because index expression is not of type number ts(7015)

on both item and name when I hover at them. And I'm not sure how to type it correctly.

EDIT: Ideal result of the transformation is the photo below: TIMEZONE_MAP_NAME

I've just put any on the map argument like TIMEZONE_LIST.map((item: any)

Update: I've changed my object declaration type to const TIMEZONE_NAME_MAP: Record<string, TimezoneListType> = {}; seems to work but I don't understand why? and Now the other part of my program is screaming as I've exported it to other places so I can use it like TIMEZONE_NAME_MAP.filter( ..so on) but does't recognize indexOf as I'm trying to use that inside the filter function. what do i do?

swoopy
  • 326
  • 4
  • 18
  • 1. `.map` operator returns one single object, no need to assign 2. you may want to return `return { ...item, lower: item.label.toLowerCase(), offsetString: 'something', };` – Nishant Jan 13 '20 at 11:28
  • I need to reassign I need the index key to be a string – swoopy Jan 13 '20 at 11:35
  • @swoopy the index of...what? You've declared `TIMEZONE_NAME_MAP` as `TimezoneListType[]` which means an *array*. Arrays' indexes are positive integers, not arbitrary strings. Moreover, your `.map` doesn't strictly perform a mapping operation - while TS might not complain about that (not actually sure), *I would* were I to do your code review. I'm sure many other people also would. I'd also take the opportunity to point out that `const hour = item.offset | 0;` is *most likely* incorrect. You might have meant `||` in which case you have a typo. If you did mean `|`, then offsets can be fractions. – VLAZ Jan 13 '20 at 11:56

3 Answers3

0

The assignment on the last line implies a for loop may be better suited to this scenario than a map. The purpose of the map is to create an array mapped to new values corresponding to the original, whereas your goal here is to create a dictionary.

PS, you also don’t seem to be using the values that you create during the mapping anywhere after assigning them (positive, minute)

  • Im using them at `offsetString` i just removed it and place 'something' for simplicity – swoopy Jan 13 '20 at 11:37
  • Noted. As for the mapping, let me phrase it in a different way. The purpose of the map method is to perform a mapping rather than to create a map. It’s mapping the values at the indexes of your array to the values at the index of a new array, rather than creating a map (dictionary in your case) that implicitly handles the mapping when provided a key. – Saahil Hamayun Jan 13 '20 at 12:01
0

Your getting that error because you are assigning an object to the array index and it is expecting you to an numeric index.

const TIMEZONE_MAP = TIMEZONE_LIST.map((item) => { 
  const positive = item.offset >= 0;
  const hour = item.offset | 0;
  const minute = (item.offset - hour) * 60;
  return TIMEZONE_NAME_MAP[index] = {  // typescript is screaming in this line.
    ...item,
    lower: item.label.toLowerCase(),
    offsetString: 'something',
  };
  });

EDIT: this would be a better way:

const TIMEZONE_MAP = TIMEZONE_LIST.map((item, index) => {
  const positive = item.offset >= 0;
  const hour = item.offset | 0;
  const minute = (item.offset - hour) * 60;
  return  {  // typescript is screaming in this line.
    ...item,
    lower: item.label.toLowerCase(),
    offsetString: 'something',
  };
  });

Edit 2 as per new requirement:

const TIMEZONE_MAP = TIMEZONE_LIST.map((item, index) => {
  const positive = item.offset >= 0;
  const hour = item.offset | 0;
  const minute = (item.offset - hour) * 60;
  let obj = {};
  obj[item.name] = {...item,
    lower: item.label.toLowerCase(),
    offsetString: 'something'};
  return  obj;
  });
Vince
  • 945
  • 7
  • 17
  • but i want that to be string ideal result of TIMEZONE_MAP would be [item.name]{ key: value} – swoopy Jan 13 '20 at 11:32
  • @swoopy, please give an example of the expected output – Vince Jan 13 '20 at 11:34
  • [string]: { ...item, lower: 'value', offsetString: 'value', } – swoopy Jan 13 '20 at 11:39
  • @swoopy, [string] is a single string but you assigning a object – Vince Jan 13 '20 at 11:44
  • okay, what would i assign to make it so the indexes of the array object is a string? – swoopy Jan 13 '20 at 11:46
  • @swoopy you cant. see here https://stackoverflow.com/questions/9526860/why-does-a-string-index-in-an-array-not-increase-the-length – Vince Jan 13 '20 at 11:52
  • okay, so I'll just change my object container to `const TIMEZONE_NAME_MAP: TimezoneListType[] = {};` how would you type it? – swoopy Jan 13 '20 at 11:55
  • getting there, how would you type `item` and the `obj` - Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{}'. No index signature with a parameter of type 'string' was found on type '{}' – swoopy Jan 13 '20 at 12:07
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/205861/discussion-between-vince-and-swoopy). – Vince Jan 13 '20 at 12:08
0

.map operator returns one single object, no need to assign

const TIMEZONE_NAME_MAP: TimezoneListType[] = TIMEZONE_LIST.map((item) => {
  const positive = item.offset >= 0;
  const hour = item.offset | 0;
  const minute = (item.offset - hour) * 60;
  return { 
    ...item,
    lower: item.label.toLowerCase(),
    offsetString: 'something',
  };
});
Nishant
  • 54,584
  • 13
  • 112
  • 127
  • but this will result on indexes being numbers, I want the indexes to be string with the value of `item.name` – swoopy Jan 13 '20 at 11:42
  • @swoopy if you want the indexes to be strings, then you don't want an array. – VLAZ Jan 13 '20 at 11:58
  • @VLAZ, i supposed - I've changed the declaration to const TIMEZONE_NAME_MAP: any = {} , how would you change the any to fit the typing? – swoopy Jan 13 '20 at 12:00