Используйте значение универсального типа для свойства, ожидающего 'number | строка | неопределенный'

В этом вопросе используется код React, но он относится к машинописному тексту, а не к реакции.

Я использую упрощенный пример, чтобы упростить чтение. У меня есть компонент MyList, который принимает один аргумент универсального типа, который передается типу реквизита.

Этот универсальный тип выводит объект, который будет использоваться для создания дочернего компонента. Я хочу указать каждый дочерний компонент, используя значение T[keyof T] || его индекс в T[].

Создание списка и использование индекса не проблема, но я не могу понять, как правильно набрать listKey, чтобы он работал с реагирующим свойством key, которое ожидает number | string | undefined.

type MyListProps<T> = {
  list: T[],
  listKey: keyof T,
  contentKey: keyof T
}

class MyList<T extends object> extends React.Component<MyListProps<T>, any> {
  public render() {
    return (
      <div>
        { this.props.list.map((value: T, index: number) => {
            const key = value[this.props.listKey];
            return (
              // Type T[keyof T] is not assignable 
              // to type 'number | string | undefined'
              <Item key = {key}>{value[this.props.contentKey]}</Item>
            );
        }
      </div>
    );
  }
}

Как я мог сделать вывод, что тип listKey можно присвоить ожидаемому типу реакций key с помощью универсального?

Честно говоря, это не так важно, поскольку key — это полумагическое свойство, добавленное реакцией, которое можно использовать для любого компонента независимо от его определения. Он используется, чтобы гарантировать, что реакция не перерисовывает компоненты, которые не изменились в списке.

David Barker 17.05.2019 10:43
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
1
172
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Поскольку вы хотите присвоить результат доступа к индексу key, вам нужно будет ограничить то, что может возвращать эта операция индекса. Один из способов сделать это — использовать ограничение на T:

class MyList2<T extends Record<string, string | number >> extends React.Component<MyListProps2<T>, any> {
  public render() {
    return (
      <div>
        { this.props.list.map((value: T, index: number) => {
            const key = value[this.props.listKey];
            return (
              <Item key = {key}>{value[this.props.contentKey]}</Item>
            );
        })}
      </div>
    );
  }
}

У этого есть недостаток, заключающийся в ограничении возможных значений, которые вы можете иметь в T, что может быть проблемой (или не в зависимости от вашего варианта использования).

Еще один более сложный вариант — ограничить только то, что будет возвращать индексация с использованием listKey. Это требует дополнительного параметра типа, но обеспечивает большую гибкость:

type MyListProps<T, LK extends PropertyKey> = {
  list: Array<T & Record<LK, string>>,
  listKey: LK,
  contentKey: keyof T
}
declare const Item: React.FC<{}>

class MyList<T, LK extends PropertyKey> extends React.Component<MyListProps<T, LK>, any> {
  public render() {
    return (
      <div>
        {this.props.list.map((value, index: number) => {
          const key = value[this.props.listKey];
          return (
            <Item key = {key}>{value[this.props.contentKey]}</Item>
          );
        })}
      </div>
    );
  }
}

let x = <MyList listKey = "a" contentKey = "a" list = {[
  { a: "", b: 0, p: {} }
]} ></MyList>

Или вы могли бы отказаться от безопасности типов в этом случае и просто использовать утверждение типа.

расширение типа PropertyKey выглядит действительно хорошим способом сделать это, я попробую, спасибо за ответ.

David Barker 17.05.2019 10:56

После его реализации я понял, что он делает, и это прекрасное решение, большое спасибо!

David Barker 17.05.2019 11:02

Другие вопросы по теме