В этом вопросе используется код 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 с помощью универсального?



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Поскольку вы хотите присвоить результат доступа к индексу 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 выглядит действительно хорошим способом сделать это, я попробую, спасибо за ответ.
После его реализации я понял, что он делает, и это прекрасное решение, большое спасибо!
Честно говоря, это не так важно, поскольку
key— это полумагическое свойство, добавленное реакцией, которое можно использовать для любого компонента независимо от его определения. Он используется, чтобы гарантировать, что реакция не перерисовывает компоненты, которые не изменились в списке.