Задать вопрос
  • Почему код со временем перестает работать, хотя раньше работал отлично?

    Aetae
    @Aetae Куратор тега JavaScript
    VDone, ну можно ещё вероятных вариантов накидать: например у тебя присутствует race condition, т.е. несколько асинхронных действий выполняются одновременно, и которое из них вернёт ответ первым доподлинно неизвестно, однако твой код ожидает определённого порядка. В старых версия хрома этот порядок соблюдался, а в новой сделали какую-то оптимизацию из-за которой одно из действий стало выполняться быстрее.(допустим скрипт из кэша быстрее стартует, чем на странице появится .board_table)

    Но всё это гадания. У тебя есть отличный способ вот прямо сейчас найти отличия в поведении твоего кода, т.к. опера и яндекс - тот же хром в своей обёртке.)
  • Как такое типизировать?

    Aetae
    @Aetae Куратор тега TypeScript
    Это не реально в рамках TS. Из-за структурной типизации тип инстанса класса не имеет никакой связи с типом самого класса окромя названия, а потому не может никаким образом ссылаться на статические свойства.
  • Почему я получаю undefined?

    Aetae
    @Aetae Куратор тега JavaScript
    webjun,
    Ошибка базового синтаксиса js. Если в квадратных скобках функции нет return - она ничего и не возвращает. React в этом плане ничего не меняет.
    recipes.map((recipe) => {
      <h2>{recipe.recipe.calories}</h2>;  //не отображается
    })
    ->
    recipes.map((recipe) => {
      return (<h2>{recipe.recipe.calories}</h2>);  
    })
    или
    recipes.map((recipe) => (
      <h2>{recipe.recipe.calories}</h2>;  
    ))


    P.S. Круглые скобки можно опустить, но при работе с React считаестя хорошим тоном заключать jsx разметку в скобки.
  • Как изменить, а не перезаписасать тип у вложенных объектов?

    Aetae
    @Aetae Куратор тега TypeScript
    Ну если хочется можно обратиться по ключу, но это не особо красиво, если ты об этом. Если б ты не нарушал правило 3.8, яб дал код по-конкретнее, то хватит и так:
    interface A extends B {
      foo: B['foo'] & {
        bar: 'bar'
      }
    }
  • Как динамически создавать экземпляры разных классов, с доступом к их типам?

    Aetae
    @Aetae Куратор тега TypeScript
    Евгений Журов, если не хочется юнион, то как я и говорил - сделай базовый интерфейс и юзай его везде, где ненужен конкретный класс.
    interface API {}
    class Animal implements API {}
    class Human implements API {}
    const getInstance = (key: keyof typeof dict): API => {};

    А для тех копмонентов в которых ты уверен что будет конкретный класс - сразу руками кастуй тип и всё. Ручной каст для таких "уверенных" случаев и придуман.)

    P.S. Кстати тот словарь можно даже расширяемым сделать:
    interface ClassDictionary {
      animal: typeof Animal,
      human: typeof Human
    }
    
    const dict = {
      animal: Animal,
      human: Human
    } as ClassDictionary;
    
    // ...
    class Car implements API {}
    dict.car = Car;
    interface ClassDictionary {
      car: typeof Car,
    }
  • Как динамически создавать экземпляры разных классов, с доступом к их типам?

    Aetae
    @Aetae Куратор тега TypeScript
    И кроме того, смущает, что по факту тип моего инстанса всегда будет Animal | Human.

    Евгений Журов, тип будет таким, пока ты не сделаешь if (instance instanceof Animal), внутри он уже чётко будет Animal, очевидно. А проверку тебе в любом случае придётся делать, так что не вижу в чём конкретно проблема? Ты хочешь вызывать произвольные методы в произвольный момент времени без проверки? Или что?
  • Как динамически создавать экземпляры разных классов, с доступом к их типам?

    Aetae
    @Aetae Куратор тега TypeScript
    Евгений Журов, ну тогда так и делать, со словарём, что тут ещё придумывать. Чужой метод всё равно вызвать в ts не получится пока с помощью проверки не конкретизируешь тип.
    Разве что можно добавить базовый интерфейс для общих методов и свойств, чтоб классы имплементировали оный, но сути это не поменяет.
  • Почему я получаю undefined?

    Aetae
    @Aetae Куратор тега JavaScript
    webjun, тип не верный:
    export interface Hit {
      recipe: Recipe[];
    }
    ->
    export interface Hit {
      recipe: Recipe;
    }

    У тебя же там единичная запись, а не массив. О чём typescript тебе явно в ошибкеах и пишет.

    Яж сказал воспользоваться генераторром. Руками ты можешь что угодно накосорезить.

    По второй ошибке: у тебя есть тип Recipe и компонент Recipe, они конфликтуют скорее всего. Также возможно сам компонент Recipe не типизирован, т.е. ts не знает какие пропсы он принимает, а какие нет.
    Сам текст ошибки говорит буквально "<список переданных пропсов> нельзя назначить в <стандартные атрибуты для React-комонента>, пропс title отсутствует в <стандартные атрибуты для React-комонента>".
  • Почему я получаю undefined?

    Aetae
    @Aetae Куратор тега JavaScript
    Ты ожидаешь что axios(сервер) тебе вернёт Welcome, а не Welcome['hits'], потому так и пиши:
    const response = await axios.get<Welcome>(
            `https://api.edamam.com/search?q=${query}&app_id=${ID}&app_key=${KEY}`
          );
    А вот в setRecipes ты уже хочешь положить именно Welcome['hits'] а не весь Welcome, потому тоже так и пиши
    React.useState<Welcome["hits"]>([])
    // ...
      setRecipes(response.data.hits)

    По сути дженерик у axios просто устанавливает какой тип будет у response.data.
  • Как отображать большое количество полигонов через ObjectManager в Яндекс картах?

    Aetae
    @Aetae Куратор тега JavaScript
    К ответу freeExec добавлю очевидное: делайте diff меду чанками, удаляйте и добавляйте только то, что изменилось.
  • Почему я получаю undefined?

    Aetae
    @Aetae Куратор тега JavaScript
    webjun, он может написать тебе
    Property 'hits' does not exist on type 'Ingredient[]'
    только если ты сам напишешь вот так await axios.get<Ingredient[]>.... Т.е. ты прямым текстом говоришь typescript'у, что в ответе сервера ждёшь МАССИВ Ingredient[], а не объект, имеющий поле hits, а потом удивляешься, что он тебе об этом прямо говорит.

    На обычном js ты можешь писать пет-проекты, но в достойной конторе ты никуда от typescript'а не убежишь, так что лучше начинай вникать пораньше. Хотя если у тебя нет бэкгранунда чистого javascript то в принцпе от того что ты на нём некоторое время по-пишешь будет и к лучшему. Зато потом, хорошенько походив по граблям, сразу проникнешься удобством typescript'a.)
  • Почему я получаю undefined?

    Aetae
    @Aetae Куратор тега JavaScript
    webjun, твоя ошибка в непонимании, что вообще тебе приходит(или вообще в базовом умении работать с объектами в javascript), а также непонимании как работает React.

    1. Тебе уже неоднократно сказали(не только я), что в responce.data у тебя корневой объект ответа, а не массив. Не массив. Не. Массив.
    Если ты хочешь положить в setRecipes массив hits, то и клади туда, блин, массив hits: setRecipes(response.data.hits).

    2. setRecipes не меняет магически на лету recipes, он обновляет state(состояние) компонента. Поэтому функция и называется useState, а не как-то ещё.
    Что при этом происходит, ты должен был прочитать в мануале к реакту, однако если упростить, то тупо будет повторно вызвана эта функция(компонент) которая отрисует компонент заново, и уже при этом, повторном вызове, значение recipes будет тем которое ты установил.
    Т.е. порядок действий происходящий у тебя:
    1. Отрисовывается компонент с recipes пустым массивом, создаётся функция fetchApi в которую замыкается пустой recipes.
    2. После отрисовки срабатывает useEffect и вызывает функцию fetchApi.
    3. Какое-то время ничего не происходит, пока идёт запрос к серверу.
    4. Пришёл ответ от сервера, он отправляется в setRecipes, выводится console.log с запомненным пустым recipes.
    5. setRecipes инициирует повторную отрисовка компонента(повторный вызов функции-компонента), при которой в recipes уже лежит то, что туда положили на предыдущем шаге. После отрисовки useEffect не срабатывает, т.к. query не менялся.
  • Почему я получаю undefined?

    Aetae
    @Aetae Куратор тега JavaScript
    webjun, ты в setRecipes всё ещё кладёшь response.data, в response.data у тебя весь ответ от сервера. Это не массив, а объект, вот этот: 6320fb286e48b959590699.png
    Ты не можешь map'ом пройтись по объекту.

    Это раз.

    recipes - может быть undefined, потому что тут
    const[recipes, setRecipes] = React.useState<Welcome>();
    не задал значение по умолчанию: useState() условно то же самое, что useState(undefined), а значит у тебя в recipes лежит undefined до тех пока не придёт ответ от сервера. А ответ от сервера может прийти через сто лет, к тому времени компонент уже нарисовался и recipes.map был вызван, т.е. undefined.map, а это ошибка и падение скрипта. TS не даёт тебе этого сделать. Ты должен либо добавить проверку, что recipes существует, либо задать значение по умолчанию, например пустой массив.

    Это два.

    В общем TypeScript - тебе друг, а не враг, он заранее не даёт тебе сделать глупые ошибки которые без него всё равно свалят твое приложение, но уже во время работы. Смотри какие он тебе подсказки выдаёт, и что он тебе пишет, он это делает не от желания поболтать.
  • Почему не распознается .tsx файл?

    Aetae
    @Aetae Куратор тега TypeScript
    Попробуй "проекты" в "projects" переименовать. На всякий случай.)
  • Почему я получаю undefined?

    Aetae
    @Aetae Куратор тега JavaScript
    webjun, тайпскрипт даёт подсказки по тем типам которые описаны. Он ничего не знает о том, что там приходит с сервера, кроме того, что ты ему сам рассказал: он работает на этапе компиляции, а ответ от сервера приходит на этапе исполнения, когда никакого тайпскрипта уже давно нет, а есть только чистый js.
  • Почему я получаю undefined?

    Aetae
    @Aetae Куратор тега JavaScript
    webjun, после console.log(recipes) добавь console.log(recipes.hits[0].recipe.dishType). Если на это будет ругаться typescript значит ты таки неправильно указал типы. Если будет выводить undefined - значит скриншоты врут.)
  • Как типизировать populate в mongoose?

    Aetae
    @Aetae Куратор тега TypeScript
    Сам mongoose не использую и ставить лень, но очевидный ответ: если метод populate умеет это делать - тыкни в него и посмотри как там сделано. Возможно там уже есть готовый дженерик для этого, который достаточно просто импортировать, ну а если нет - не вижу сложности выдрать тип и написать что надо по образу и подобию.