Объект с универсальными ключами в машинописном тексте

Я хотел бы создать общую функцию, которая будет принимать объект, затем выполнять некоторые преобразования и возвращать новый объект с теми же ключами и разными значениями. Я пытаюсь сделать его «строго типизированным», чтобы каждый, кто его использует, имел преимущества TS, а несуществующие ключи должны выдавать ошибку.

Что у меня есть на данный момент:

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

Он работает хорошо, но я ищу решения, чтобы решить эту проблему:

  1. Удалить утверждение типа const result = {} as Result<T>

  2. Удалите утверждение типа (Object.keys(mapper) as (keyof T)[]) (или используйте Object.entries, но, похоже, в этом случае также требуется утверждение типа)

Могу ли я реализовать то же самое, но более «чистым» способом в Typescript?


person dieTrying    schedule 31.12.2019    source источник


Ответы (1)


Object.keys возвращает всегда string[], поэтому вам потребуется преобразование.

Меньшая и более надежная версия будет использовать reduce. Еще одно небольшое улучшение - использовать тип исходного ключа с 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.keys(obj) as Array<keyof T>).reduce((result, key) => {
      result[key] = () => obj[key];
      return result;
  }, {} as Result<T>)
}

const a = transform(hash)

a.first() // returns "string"
a.second() // return "number"
person felixmosh    schedule 31.12.2019
comment
Я не вижу, чтобы reduce вообще прибавлял устойчивости (и, если на то пошло, не меньше); но это действительно увеличивает сложность по сравнению с простым созданием объекта и добавлением к нему, не в последнюю очередь введением ножного пистолета в забвение строки return result;. Как сказали другие, reduce злоупотребляют. - person T.J. Crowder; 31.12.2019
comment
Что, черт возьми, кто мог подумать, изменив : на in, чтобы это исправить? Спасибо! - person steve moretz; 20.05.2021