Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

207
Visualizações
How do I iterate through child objects and convert all non-object values to string

I currently have an existing method where I convert all key value pairs to string

export function convertObjValueToString<T>(data: Record<string, T>): Record<string, string> {
  return Object.keys(data).reduce((acc, key) => {
    return {
      ...acc,
      [key]: String(data[key]),
    };
  }, {});
}

but it is currently limited to the first level of an object. I want it to test deeper if for instance the value is another child object

{ 
    id: 2, 
    metadata: { 
        booleanValue: false, 
        someOtherKey: { 
            booleanValue: false
        }
    }
}

expected result would be:

{ 
    id: '2', 
    metadata: { 
        booleanValue: 'false', 
        someOtherKey: { 
            booleanValue: 'false'
        }
    }
}
about 4 years ago · Juan Pablo Isaza
3 Respostas
Responde à pergunta

0

You can use Object.entries() to convert the object to an array of [key, value], map the array of pairs and transform according to type, and then convert back to an object using Object.fromEntries():

const convertObjValueToString = data => {
  if (Array.isArray(data)) return data.map(convertObjValueToString)

  if (data !== null && typeof data === 'object') return Object.fromEntries(
    Object.entries(data)
    .map(([k, v]) => [k, convertObjValueToString(v)])
  )

  return String(data)
}


const obj = {
  id: 2,
  metadata: {
    booleanValue: false,
    someOtherKey: {
      booleanValue: false,
      nullKey: null,
      undefinedKey: undefined,
    }
  }
}

const result = convertObjValueToString(obj)

console.log(result)

Types

You'll need to use a recursive type both to describe the original object, and then resulting object (TS Playground):

type NestedValues<T> =
  | T
  | { [property: string]: NestedValues<T> }
  | NestedValues<T>[];

const convertObjValueToString = (data: NestedValues<any>): NestedValues<string> => {
  if (Array.isArray(data)) return data.map(convertObjValueToString)

  if (typeof data === 'object') return Object.fromEntries(
    Object.entries(data)
    .map(([k, v]) => [k, convertObjValueToString(v)])
  )

  return String(data)
}
about 4 years ago · Juan Pablo Isaza Relatório

0

export function convertObjValueToString<T extends object>(data: Record<string, T>): Record<string, string> {
  return Object.keys(data).reduce((acc, key) => {
    const currentPropValue = data[key];
    if(currentPropValue === Object(currentPropValue)) {
      return {
        ...acc,
        [key]: convertObjValueToString(currentPropValue)
      };
    }

    return {
      ...acc,
      [key]: String(data[key]),
    };
  }, {});
}

I got the solution right but I having problem fixing the types though as I am getting a argument of type 'T' is not assignable to parameter of type 'Record<string, object>' under my if condition

about 4 years ago · Juan Pablo Isaza Relatório

0

Consider this example:

type Values = number | boolean | string
type Dictionary = { [prop: string]: Dictionary | Values }

const isObject = (data: unknown): data is Dictionary => 
  typeof data === 'object' && data !== null

type ObjToString<Obj extends Dictionary> = {
  [Prop in keyof Obj]:
  (Obj[Prop] extends Dictionary
    ? ObjToString<Obj[Prop]>
    : (Obj[Prop] extends Values
      ? `${Obj[Prop]}`
      : never)
  )
}

const record = <
  Key extends PropertyKey,
  Value
>(key: Key, value: Value) =>
  ({ [key]: value })

const merge = <
  Obj extends Dictionary,
  Part extends Dictionary
>(obj: Obj, part: Part) =>
  ({ ...obj, ...part })

const convert = <
  Data extends Dictionary
>(data: Data): ObjToString<Data> =>
  Object.keys(data).reduce((acc, elem) => {
    const value = data[elem];

    const maker = isObject(value) ? convert : String

    return merge(acc, record(elem, maker(value)))
  }, {} as ObjToString<Data>)


const result = convert({
  id: 2,
  metadata: {
    booleanValue1: false,
    someOtherKey: {
      booleanValue2: false
    }
  }
})

const id = result.id // `${number}`
const booleanValue2 = result.metadata.someOtherKey.booleanValue2 // "false"

Playground

Values - represents allowed primitive values of the object

Dictionary - represents allowed shape/interface of argument

isObject - custom typeguard. Check whether passed value is an object or not

ObjToString - type representation of business logic. Converts passed object to object where all primitive values are stringified

record - small helper (can be inlined)

merge - small helper (can be inlined)

convert - main function. Recursively goes through each key and converts value to string or makes recursive call

As you might have noticed result is infered and TS is aware which properties are allowed an which are not. Please keep in mind that I have passed literal value of object. If you pass a reference TS still infer allowed properties but values wll be more wider. For instance instead of "false" you will get "true"|"false"

If your argument should match some interface it is better because in that case TS will infer required properties more precisely

about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda