Задать вопрос
  • Как описать OR логику в интерфейсах?

    Aetae
    @Aetae Куратор тега TypeScript
    soofftt91, сам одно время юзал подобный хак, но в итоге постарался отказаться, пересмотрев интерфейсы, из-за следующих причин: в более сложно-составных типах ошибки становятся жуткими; начинает подтормаживать ТС; сам тип всё равно выдаёт в подсказке все-все ключи, что крайне неудобно если их больше трёх.
  • Почему код со временем перестает работать, хотя раньше работал отлично?

    Aetae
    @Aetae Куратор тега JavaScript
    VDone, вообще поскольку это ваш код, вы должны разумно управлять загрузкой скриптов и точно знать когда там что вызывать.

    Но если говорить прям универсально, то можно использовать кастомное событие:
    // тот скрипт, что создаёт .board__table
    function setTableReady(detail) {
      const event = new CustomEvent('my-table:ready', { detail });
      window.myTableReady = event;
    	window.dispatchEvent(event);
    }
    
    // когда таблица готова к использованию
    setTableReady();
    // тот скрипт, что работает с .board__table
    function onTableReady(callback) {
      if (window.myTableReady)
        callback(window.myTableReady);
      else
        window.addEventListener('my-table:ready', callback, { once: true });
    }
    
    onTableReady(() => {
      // точка входа запускающая весь код
    });

    Так порядок будет не важен в принципе.

    Если скрипт чужой и не представляет ни возможностей для изменения, ни внешних интерфейсов, то можно использовать MutationObserver для слежения за появлением самого элемента на странице. Но это уже так себе хак.
  • Почему код со временем перестает работать, хотя раньше работал отлично?

    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.