Данные снаружи требуют проверки

any отключает значительную часть проверки типов для значения. unknown оставляет значение неизвестным, пока код не проверит его форму. Проверка typeof, условие или предикат типа могут уточнить информацию, доступную TypeScript.

Типы не проверяют сетевой ответ во время выполнения. Запись as Article[] сама по себе не превращает произвольный JSON в корректный список. Для внешних данных нужны проверки или библиотека валидации.

Опишите варианты состояния

У каждого варианта ниже есть поле status с конкретным строковым значением. После проверки этого поля TypeScript понимает, какие остальные свойства доступны.

typescript
type Article = { id: string; title: string };

type LoadState =
  | { status: "loading" }
  | { status: "success"; articles: Article[] }
  | { status: "error"; message: string };

function getCaption(state: LoadState): string {
  switch (state.status) {
    case "loading": return "Загружаем статьи";
    case "success": return `Статей: ${state.articles.length}`;
    case "error": return state.message;
  }
}

Сократите невозможные сочетания

Если хранить отдельно isLoading, error и data, можно случайно получить состояние «загружается, но уже ошибка». Объединение делает допустимые варианты яснее. При этом старые данные во время повторной загрузки иногда нужны: такой сценарий следует отдельно описать в модели.

Включите строгую проверку проекта и исправляйте ошибки на границе данных. Начните с API и публичных функций, где ясный контракт полезен сразу нескольким частям приложения.

Попробуйте сами

Добавьте состояние idle до первого запроса. Затем расширьте модель повторной загрузкой с уже имеющимися статьями и обновите функцию подписи.

Стоит ли заменять каждое any на unknown?

Механическая замена не создаёт хороший контракт. Используйте unknown на границах неизвестных данных, а внутри проверенного кода описывайте конкретные типы.

Документация и следующий шаг

Продолжите практику: Vue 3: состояние, которое обновляет интерфейс.