Home > Blockchain >  Loosening variable type
Loosening variable type

Time:03-30

I'm trying to define a function that returns an object mapping properties (strings) to a lists of strings, except when there's only one item in the list, then I want to map to the string.

type MyType = { [key: string]: string | string[] } 

export function myFunc(s: string): MyType {
  const result: MyType = {}

  for (const param of s.split('&')) {
    const [key, val] = param.split(/=(.*)/s, 2)
    if (Object.prototype.hasOwnProperty.call(result, key)) {
      result[key].push(val ? val : '')  // Type error happens here because there's no string.push()
    } else {
      result[key] = [val ? val : '']
    }
  }

  for (const [key, val] of Object.entries(result)) {
    if (val.length === 1) {
      result[key] = val[0]
    }
  }

  return result
}

What's the right thing to do here? I could move the first for loop into its own function that that returns { [key: string]: string[] } and then do result: MyType = thatFunction() or I can have two variables

  const _result: { [key: string]: string[] } = {}
  // [do the first for loop]
  const result = _result as MyType
  // [do the second for loop]
  return result

Is there a way to do this type of stuff, where I want to write something as a given type in my code, then immediately transform that value into a stricter/looser type without an intermediate variable name?

CodePudding user response:

Well, there is a limitation narrowing down the type with bracket notation. But there is a workaround for that which is to assign that property to a temp variable type check it and then assign it :

 const temp = result[key];
 if (Array.isArray(temp)) { // you need to narrow down the type 
    temp.push(val ? val : '')
 }  


if (Array.isArray(result[key])) { // sadly this won't work
    result[key].push(val ? val : '')
 } 

Playground

Edit

As your code flow guarantees that result[key] is always an array. You can safely assert that is an array with a cast like this :

  ( result[key] as string[]).push(val ? val : '') 
  • Related