Как добавить длинный список статических свойств к функции в Typescript

#typescript

#typescript

Вопрос:

Я пытаюсь ввести эту функцию, к которой добавлен длинный список статических строк в качестве свойств, которые возвращают свойство в виде строкового значения:

 const arr = ["a", "b", "c"]; // actual list has about 140 items

const f = (tag: string | undefined) => tag;

arr.forEach(key=> {
  f[key] = f(key)
})

console.log(f.a) // "a"
console.log(f.b) // "b"
console.log(f.c) // "c"
console.log(f.d) // undefined  

Ошибки:

 Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '(tag: string) => string'. No index signature with a parameter of type 'string' was found on type '(tag: string) => string'.
Property 'a' does not exist on type '(tag: string) => string'.
Property 'b' does not exist on type '(tag: string) => string'.
Property 'c' does not exist on type '(tag: string) => string'.
Property 'd' does not exist on type '(tag: string) => string'.
  

Typescript Playgound


Ответ №1:

Во-первых, вам нужно объявить массив статических свойств, as const чтобы создать тип ['a', 'b', 'c'] вместо string[] .

 const arr = ["a", "b", "c"] as const;
  

Теперь получите эти строковые константы как объединение строковых литералов, получив тип этого массива, а затем индексируя этот тип с помощью number .

 type Keys = (typeof arr)[number] // "a" | "b" | "c"
  

Затем объявите тип функции и статические свойства отдельно.

 type TagFn = (tag: string | undefined) => string | undefined
type StaticProps = { [key in Keys]: string }
  

Теперь вы можете пересекать эти типы, чтобы сделать статические свойства частью типа функции.

 type TagFnWithStatic = TagFn amp; StaticProps
  

Typescript не понравится, если вы создадите функцию и скажете, что это TagFnWithStatic тип без объявленных статических свойств, потому что эти свойства должны быть определены, чтобы удовлетворять типу. Чтобы исправить это, давайте создадим статические свойства как их собственный объект отдельно.

 const staticProps = arr.reduce((result, prop) => {
  result[prop] = prop;
  return result
}, {} as StaticProps)
  

Который затем может быть объединен с функцией при присвоении переменной через Object.assign()

 const f: TagFnWithStatic = Object.assign(
  (tag: string | undefined) => tag,
  staticProps
)
  

Теперь следующее должно работать так, как вы ожидаете:

 f.a // type: string
f.b // type: string
f.c // type: string

f.d // type error, because static property is not present in `arr`
  

Игровая площадка