Как узнать, какой тип использовать в TypeScript? - PullRequest
1 голос
/ 09 апреля 2020

Основной вопрос

Я, кажется, продолжаю сталкиваться с этим в разных формах в машинописи. Иногда функция или какой-либо объект требует определенного c интерфейса, и я ищу общий набор шагов, которые необходимо выполнить, чтобы выяснить, что это за интерфейсы.

Пример кода

Я пытаюсь написать функцию, которая будет перебирать различные цвета темы Material-UI. У меня возникают проблемы даже при доступе к индивидуальному, когда я начинаю передавать параметры для выполнения работы.

Работает как ожидалось

const printColor = () => {
  const theme = createMuiTheme();
  const color = theme.palette.primary['main'];
  console.log(color);
};
printColor(); // prints #3f51b5 to the console

Неудачный пример

const printColor = (key: string) => {
  const theme = createMuiTheme();
  const color = theme.palette.primary[key];
  console.log(color);
};
printColor('main');

Ошибка:

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'PaletteColor'.
  No index signature with a parameter of type 'string' was found on type 'PaletteColor'.

Дальнейшие мысли

Кажется, мне нужно добавить какой-то тип для параметра key? Я охотился вокруг, чтобы попытаться выяснить, какой это будет тип. Почему это работает, когда я обращаюсь к нему напрямую в виде строки, а не когда я передаю его в качестве параметра?

Есть ли способ, которым вы быстро определяете, какой тип использовать при возникновении таких ошибок типа? ?

Запустить код

По запросу, вот ссылка, чтобы поиграть с кодом самостоятельно. https://stackblitz.com/edit/typescript-6rntqm

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

1 Ответ

1 голос
/ 09 апреля 2020

Таким образом, «правильный» ответ на этот вопрос, вероятно, выглядит следующим образом:

import { PaletteColor } from "@material-ui/core/styles/createPalette";

, а затем

const noLongerFails = (key: keyof PaletteColor) => {
  const theme = createMuiTheme();
  const color = theme.palette.primary[key];
  console.log(color);
};

Обратите внимание, что мы хотим, чтобы key был одним из ключей PaletteColor, поэтому мы используем оператор типа keyof, чтобы превратить тип объекта в объединение его ключей.

Отслеживание правильного типа PaletteColor и места его экспорта немного неприятно (может быть, у кого-то есть лучшее решение, чем то, что я сделал), но оно выглядит так:

  • наведите курсор мыши на theme.palette.primary в вашей IDE и посмотрите, что IntelliSense говорит о его типе:

    IntelliSense

    В данном случае написано (property) Palette.primary: PaletteColor. Так что если нам повезет, экспортируется тип, называемый PaletteColor.

  • Если у вас есть соответствующая node_modules информация для material-ui, установленная локально, вы можете найти ее для этого типа. Если нет, вы всегда можете взглянуть на исходный код и найти его . К счастью, есть один удар , и вы можете видеть, что он экспортируется как interface в styles/createPalette.d.ts.

  • Мы импортируем оттуда, и это работает!


Если мы не смогли найти соответственно экспортируемый тип, мы могли бы вместо этого начать используя запросы типов TypeScript, чтобы дразнить требуемый тип из вещей, которые мы можем импортировать:

type MyPaletteColor = ReturnType<typeof createMuiTheme>["palette"]["primary"];

Давайте сделаем это шаг за шагом. Учитывая именованное значение, такое как createMuiTheme, мы можем запросить TypeScript для его типа, используя оператор запроса типа typeof . (Не путать с оператором runtime typeof. См. этот ответ для подробного объяснения различия между именами типов и именами значений) Так что typeof createMuiTheme является типом функции :

type CreateMuiThemeType = typeof createMuiTheme;
// type CreateMuiThemeType = (options?: ThemeOptions | undefined, ...args: object[]) => Theme;

Теперь эта функция возвращает Theme. Чтобы получить этот тип (делая вид, что мы его еще не импортировали), мы можем использовать тип утилиты ReturnType:

type MyTheme = ReturnType<CreateMuiThemeType>;
// type MyTheme = Theme;

Наконец, мы знаем, что тип Вы ищете primary свойство palette Theme. Для этого мы можем использовать типов поиска с использованием индексированной записи доступа:

type MyPalette = MyTheme["palette"];
// type MyPalette = PaletteColor;

type MyPaletteColorAlso = MyPalette["primary"];
// type MyPaletteColorAlso = PaletteColor;

Мы можем свернуть их в одну строку, как в MyPaletteColor выше. И если у нас есть собственное определение MyPaletteColor, мы можем использовать его вместо PaletteColor:

const alsoWorks = (key: keyof MyPaletteColor) => {
  const theme = createMuiTheme();
  const color = theme.palette.primary[key];
  console.log(color);
};

, и это тоже работает.


Хорошо, надеюсь, это поможет; удачи!

Stackblitz ссылка на код

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...