Здравствуйте! У меня есть вопрос по типизации в TypeScript. У меня есть компонент Posts, который отображает список постов в PostList. Каждый пост состоит из трех полей: id, title и body. В состоянии по умолчанию я заранее определил несколько постов, в полях title и body находятся буквы для удобства просмотра при сортировке.
В состоянии selectedSort я храню параметр, который определяет, по какому критерию происходит сортировка: title или body. Это значит, что сортировка ведется либо по заголовку, либо по содержимому поста, которые выступают в роли ключей в объекте post.
У меня возникла проблема с типизацией хука и функции sortPosts. Все мои попытки не приводили к успеху. Я использовал тип <string> в useState, однако получаю ошибку: "Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'IPost'. No index signature with a parameter of type 'string' was found on type 'IPost'."
Почему возникает ошибка о том, что элемент selectedSort имеет неявный тип any, если я указал, что тип в useState – строка? Можете помочь с типизацией хуков и функции sortPosts?
Вот код компонента:
<pre><code class="typescript">export interface INewPost {
title: string
body: string
}
export const Posts = () => {
const [selectedSort, setSelectedSort] = useState<string>('')
const [posts, setPosts] = useState<IPost[]>([
{ id: 1, title: 'b', body: 'b' },
{ id: 2, title: 'd', body: 'd' },
{ id: 3, title: 'a', body: 'c' },
{ id: 4, title: 'c', body: 'a' },
])
const sortPosts = (sort: string) => {
console.log(sort)
setSelectedSort(sort)
setPosts(
[...posts].sort((a, b) => a[selectedSort].localeCompare(b[selectedSort]))
)
}
const a...
Причина, по которой вы получаете ошибку в TypeScript, связана с использованием переменной `selectedSort` в качестве ключа для индексации объектов типа `IPost`. Вы типизируете `selectedSort` как `string`, но TypeScript не гарантирует, что значение `selectedSort` будет одним из ключей интерфейса `IPost`. Давайте рассмотрим, как это можно исправить.
Во-первых, вам следует определить, какие ключи будут использоваться для сортировки. Вы можете использовать строковый литеральный тип, чтобы ограничить возможные значения `selectedSort` до `'title'` или `'body'`. Таким образом, вы сможете дать TypeScript понять, что `selectedSort` всегда будет одним из этих значений.
Вот как можно изменить ваш код:
```typescript
export interface IPost {
id: number;
title: string;
body: string;
}
type SortKey = 'title' | 'body';
export const Posts = () => {
const [selectedSort, setSelectedSort] = useState<SortKey>('title');
const [posts, setPosts] = useState<IPost[]>([
{ id: 1, title: 'b', body: 'b' },
{ id: 2, title: 'd', body: 'd' },
{ id: 3, title: 'a', body: 'c' },
{ id: 4, title: 'c', body: 'a' },
]);
const sortPosts = (sort: SortKey) => {
console.log(sort);
setSelectedSort(sort);
setPosts(
[...posts].sort((a, b) => a[sort].localeCompare(b[sort]))
);
}
// Остальной код компонента
};
```
### Изменения, которые я внёс:
1. Я добавил тип `SortKey`, который представляет собой объединение строковых литералов `'title'` и `'body'`. Теперь `selectedSort` и параметр `sort` функции `sortPosts` имеют этот тип.
2. В вызове `sort` внутри функции `sortPosts` используется тот же ключ, что и переданный в качестве параметра, что исключает возможность использования потенциально недопустимого значения.
Теперь TypeScript сможет проверить, что значением `selectedSort` и параметра `sort` могут быть только `'title'` или `'body'`, и не будет выдавать ошибку при индексации объекта `IPost`.
<code>keyof IPost</code>