React Typescript: вызывает ли неодобрение вывод в зависимости от типа на несколько уровней?

#reactjs #typescript

Вопрос:

У меня есть существующий проект React Javascript, который я переношу на Typescript.

Мой существующий код имеет действительно хороший однонаправленный поток, который я хотел бы сохранить при добавлении типов. В настоящее время это происходит следующим образом:

 1. Component: FoobarListComponent -> useQueryFetchFoobars()

2. Hook: useQueryFetchFoobars() -> FoobarApi.list()

3. API: FoobarApi.list() -> axios.get("/api/v1/foobars")
 

Поскольку он написан на JS, часто неясно, каковы типы ответов конечных точек API. В приведенном выше примере нет ввода текста, поэтому разработчик понятия foobar не имеет, как выглядит объект. Вот где я хотел бы использовать Typescript.

Я хотел бы ввести все полезные данные моего ответа API. Однако я бы предпочел, чтобы об этом знал только уровень API (# 3 в последовательности выше ^), потому что в настоящее время существует четкое разделение между Components -> Hooks -> APIs . Если я делаю это на другом уровне, это кажется немного неправильным… Кроме того, я бы предпочел не экспортировать типы, потому что в настоящее время мои компоненты никогда не импортируются напрямую с уровня API.

Это пример того, что я бы предпочел не делать:

 import React from "react";
import useQueryFoobars from "hooks/useQueryFoobars";
import { FoobarListResponseType } from "apis/foobar";

const SomeComponent = () => {
  const { data } = useQueryFoobar<FoobarListResponseType | null>();

  ...
}
 

Серверная часть написана плохо, поэтому я не могу ожидать, что все объекты будут выглядеть одинаково при доступе к одному и тому же ресурсу. Под этим я подразумеваю, что иногда API-интерфейсы detail и list API возвращают объекты различной формы, например, так:

 GET /api/v1/foobars
[
  { id: "f1", name: "Baz" },
  { id: "f2", name: "Lorem" },
]

GET /api/v1/foobar/f1
{ id: "f1", name: "Baz", email: "something@yahoo.com , address: "..." },

 

Поэтому я хотел бы иметь возможность вводить каждую конечную точку по отдельности.

Одно из решений, о котором я думал, заключалось в экспорте типов внутри файлов API. Однако не означает ли это, что Typescript должен будет вывести мой тип на 2 уровня ниже? API -> Hook -> Component?

  1. Приемлемо ли это в мире TS?
  2. Верно ли мое предположение, что TS сможет определить тип?

Или ожидается, что типы будут явно установлены на каждом уровне? Пожалуйста, дайте мне знать, если я ошибаюсь, я впервые использую TS.

Ответ №1:

Почему вы боитесь импортировать типы? Они практически не существуют во время выполнения и ничего не добавляют к результирующему размеру пакета.

В любом случае, typescript имеет довольно хороший вывод типа, не требуя явного ввода, но это также зависит от того, как вы настроили свой tsconfig.json .

Следовательно, в некоторой степени возможно иметь типы только на уровне API, сохраняя при этом строгую типизацию в модулях, которые используют API. По большей части ваш пробег будет зависеть от вашей IDE и от того, включены ли вы allowJs в tsconfig (если вы все еще смешиваете typescript с javascript).

Для вашего примера, если вы просто объявите FoobarApi.list() как:

 namespace FoobarApi {
  export const list = () => axios.get<FoobarListResponseType>("/api/v1/foobars");
}

export default FoobarApi;
 

Тогда это вся информация о типе, необходимая typescript для определения типа data свойства для ответа.

Комментарии:

1. Спасибо за быстрый ответ! Чтобы ответить на ваш вопрос: я не решаюсь импортировать типы, потому что 1) мне кажется, что я начну смешивать типы с файлами, которые когда-то были сосредоточены исключительно на чем-то одном 2) Я не уверен, где хранить мои типы. src/types/api ?

2. @bigpotato Я обычно храню их внутри файла, вызываемого types.ts в папке, в которой они используются. Затем я импортирую типы, используя import type {TypeA, TypeB, etc...} from module/types . В любом случае, я понимаю вашу нерешительность, но если вы используете import type синтаксис, я думаю, это также может помочь прояснить, что эти импортные данные предназначены для информации о типе