Búsqueda de sitios web

javascript - Objeto con claves genéricas en typescript


Me gustaría crear una función común que tome un objeto, luego haga algunas transformaciones y devuelva un nuevo objeto con las mismas claves y valores diferentes. Estoy tratando de que sea "fuertemente tipada", así que todos los que la usen tendrán los beneficios de TS y las claves que no existan deberían generar un error.

Lo que tengo por ahora:

const hash = {
  "first": 1,
  "second": 2,
  "third": 3,
}

type Mapper<T> = {
  [key in keyof T]: number
}

type Result<T>= {
  [key in keyof T]: () => number
}

const transform = <T>(mapper: Mapper<T>) => {
  const result = {} as Result<T>

  (Object.keys(mapper) as (keyof T)[]).map(key => {
    result[key] = () => mapper[key]
  })

  return result
}

type Hash = typeof hash

const a = transform<Hash>(hash)

a.first()
// a.fifth() OK error

Funciona bien, pero estoy buscando soluciones para resolver esto:

  1. Eliminar la afirmación de tipo const result={} as Result<T>

  2. Elimina la afirmación de tipo (Object.keys(mapper) as (keyof T)[]) (o usa Object.entries, pero parece que en este caso también requiere afirmación de tipo)

¿Podría implementar lo mismo, pero de una manera más "limpia" en Typescript?

Respuesta #1

Object.keys devuelve siempre string[], por lo tanto necesitarás la conversión de tipo.

Una versión más pequeña y robusta usaría Object.fromEntries. Otra pequeña mejora sería usar el tipo de la clave original, con T[Key].

const hash = {
  "first": "someString",
  "second": 2,
  "third": 3,
};

type Result<T>= {
  [Key in keyof T]: () => T[Key]
};

const transform = <T extends object>(obj: T): Result<T> => {
  return Object.fromEntries(
    Object.keys(obj).map(
        (key) => [key, () => obj[key as keyof T]]
    )
  ) as Result<T>;
}

const a = transform(hash);

const first = a.first(); // returns "string"
//    ^? const first: string
const second = a.second(); // return "number"
//    ^? const second: number

Enlace del parque

Artículos relacionados