Ответы пользователя по тегу TypeScript
  • Как сделать продвинутый типизированный Generic для компонента React таблицы?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Надо явно создать union:
    type ITableColumn<
      DataInterface extends object, 
      Keys extends keyof DataInterface = keyof DataInterface
    > = {
      [K in Keys]: {
        key: K;
        title: React.ReactNode;
        hasSort?: boolean;
        render?: (item: DataInterface[K]) => React.ReactNode;
      }
    }[Keys];
    Ответ написан
    4 комментария
  • Как правильно определить тип функции и события?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Мужик. Ты спик инглиш или как? MouseEventHandler переводится как "дрессировщик мышей для эвента" "обработчик событий мыши". KeyboardEventHandler как что? Правильно, "обработчик событий клавиатуры".
    Давайте подумаем, что же функция с такими типам может ожидать на вход, а? Может, соответственно, события мыши или клавиатуры(MouseEvent/KeyboardEvent)? Да не, бред какой-то.

    Но окей, дальше мы назначили пропсам интерфейс, где getCity таки имеет такой тип. И куда же мы передаём этот getCity? А передаём мы его в onSubmit. Скажи же мне, друже, submit - это событие клавиатуры? Или может быть это событие мыши? Ты уверен? Вот и мне кажется что нет.
    Ответ написан
  • Как использовать useSlots().default() vue3 внутри script setup?

    Aetae
    @Aetae Куратор тега JavaScript
    Тлен
    о какой рендер функции идет речь?

    render-function

    Это более низкоуровневый вариант работы с vue, вместо использования <template>.(под капотом <template> компилируется в render-функцию)

    Render-функцию можно возвращать из setup, можно класть в свойство render.
    При script setup, можно сделать так:
    <template>
      <div>
        <render/>
      </div>
    </template>
    
    <script setup lang="ts">
      import { h, useSlots } from 'vue'
    
      const slots = useSlots();
      const render = () => {
        return h('div', slots.default());
      };
    </script>

    Но не нужно в подавляющем большинстве случаев. Мешать всё в одну кучу - весьма опасно.
    Ответ написан
    Комментировать
  • Как улучшить качество камеры в агуляр пва?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    1. Typescript тут не при чём.
    2. Если ты используешь метод из "camera-hardware", то проблема очевидна. Если из "camera-software", то хз, должно работать.
    Ответ написан
    Комментировать
  • Как грамотно настроить алиасы импортов?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Ну собсно по хардкору:
    1. Invalidate Caches если ещё не сделал.
    2. Закрыть, удалить папку .idea, открыть чтоб распарсил заново.
    3. Создать новый проект с заведомо рабочим конфигом и перекидывать туда кусками пока не сломается и так найти виновника.
    Ответ написан
  • Как дополнить библиотеку RxJs функцией update() для запуска next()?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Трогать родной BehaviorSubject не стоит, не одному тебе потом с ним работать.

    Ты мог бы написать свой вариант довольно просто таким образом:
    class DistinctBehaviorSubject<T> extends BehaviorSubject<T> {
      next(value: T) {
        if (this.value !== value)
        	super.next(value);
      }
    }
    Но я на вскидку не скажу какие тут могут быть подводные камни.)
    Ответ написан
    1 комментарий
  • Как создать декоратор на typescript для слежения за изменениями?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    На вскидку не вижу проблемы, что-то такое должно сработать:
    function doSomething(param: string, value: unknown) {
      console.log('doSomething', param, value);
    }
    
    function WebworkerParam(param: string){
      return (target: any, key: PropertyKey) => {
        let subscription: Subscription;
        let innerValue: any;
    
        Object.defineProperty(target, key, {
          get() {
            return innerValue;
          },
          set(value) {
            if (subscription)
              subscription.unsubscribe();
    
            if(value instanceof BehaviorSubject)
              subscription = value.subscribe(newValue => doSomething(param, newValue));
            else 
              doSomething(param, value);
    
            innerValue = value; 
          }   
        })
      }
    }
    Ответ написан
    1 комментарий
  • Можно ли в typescript создать переменную определённого типа динамически, имея параметр строчного типа?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    class User {}
    
    interface Types {
      number: number;
      dog: string; 
      user: User
    }
    
    function add<K extends keyof Types>(type: K): Types[K] {}
    Ответ написан
    Комментировать
  • Как типизировать класс с динамическими именами методов создаваемых в конструкторе?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    TypeScript очень плохо относится к динамическим членам класса. По сути в самой декларации класса ты ничего не сможешь с этим поделать, и тебе придётся руками кастовать то что надо.

    Однако в целях поддержки лекаси ты можешь просто подменить тип, что-то вроде:
    type MethodNames<T extends string> = `get${T}s` | `create${T}` | `get${T}`;
    
    interface IAPI {
      new <T extends string>(type: T, url: string): {
        [K in MethodNames<T>]: Function
      }
    }
    
    export default API as unknown as IAPI;
    сработает как надо. Естественно ты можешь доработать интерфейс IAPI до полного совпадения.

    При декларации самого класса ты максимум можешь добавить неспецифичную index signuture, условно:
    type MethodNames<T extends string> = `get${T}s` | `create${T}` | `get${T}`;
    class API {
      [key: MethodNames<string>]: Function
    
      _url;
    
      constructor(type: string, url: string) {
        this._url = url;
    
        this[`get${type}s`] = this._readMany;
        this[`create${type}`] = this._create;
        this[`get${type}`] = this._read;
      }
    
      _readMany(params = {}) {
        const options = getApiOptions(Method.GET);
        const url = new URL(this._url);
        url.search = new URLSearchParams(params);
        
        return fetch(url.toString(), options);
      }
    
      _create(body) {
        const options = getApiOptions(Method.POST, body);
        
        return fetch(this._url, options);
      }
    
      _read(id) {
        const options = getApiOptions(Method.GET);
        
        return fetch(`${this._url}/{id}`, options);
      }
    }

    Но это уже будет не так удобно и чётко.
    Ответ написан
    4 комментария
  • Как исправить ошибку Element' is not assignable to type в React?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Ну очевидно, что NavLink не принимает функцию в качестве children. Могу предположить, что код у тебя для одной версии роутера, а используется другая.
    Ответ написан
    5 комментариев
  • Как вывести тип данных Data в заголовок?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    У тебя две совершенно разные проблемы в одном вопросе:

    1. TS тебе пишет ошибку, что тип Date не может быть children'ом для компонента, и это так. Однако дело в том, что тип у тебя задан неверно, на самом деле у тебя там никакой не Date а банальный string. Если ты поправишь типы, то всё заработает и выведет тебе то что ты передаёшь, т.е. 2012-03-23T08:25:44.962Z.

    2. Чтоб превратить строку 2012-03-23T08:25:44.962Z в строку Created 7 years ago надо либо руками написать соответствующую функцию, либо воспользоваться какой-либо библиотекой для работы с датами. Например с помощью moment это будет выглядеть примерно так:
    const createdFromNow = `Created ${
      moment.duration(moment().diff(data.createdAt)).humanize()
    } ago`;
    Ответ написан
    Комментировать
  • В чем преимущества TS?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    А ещё динамическая типизация сильно экономит время на написание кода - это очень нехилая оптимизация рабочего процесса.

    Это утверждение верно относительно языков с изначально статической типизацией против языков с динамической, но не верно для TS как такового. Если не использовать маньячные правила типа обязательного ручного проставления типов, то в 80% случаев TS сам прекрасно выводит тип, без лишних телодвижений.
    Огромное ускорение от типизированого автокомплита в IDE и отсутствия возможности, например, случайно кинуть в функцию объект вместо строки, с лихвой перекрывает оставшиеся 20%.
    Редкие случаи когда TS писал мне "какую-то хрень" и отказывался что-то делать, заставляя сидеть и разбираться - на поверку оказывались сильно неочевидными косяками в моём коде, которые могли бы привести к реальным багам.
    Ответ написан
    Комментировать
  • Как предписать тип классу так, чтобы ts считал что мы унаслодовались?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Можно с помощью declaration merging, но осторожно. В таких штуках все риски ты берёшь на себя:
    class Widget {
      render() {
        this.doStuff();
      }
    }
    
    interface Widget {
        doStuff(): string
    }
    
    // потом это сделает сторонний код
    Widget.prototype.doStuff = () => 'doingstuff';
    Ответ написан
    Комментировать
  • Как синхронизировать схему БД с использованием TypeORM между микросервисами?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Ну как обычно со всем остальным: вынести в общую библиотеку либо вынести в гит-модуль.
    Ответ написан
    Комментировать
  • Как правильно рендерить рекурсивный массив используя useMemo?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    useMemo - это не магическое заклинание. Оно работает сверяя изменения переданных props не более того.
    В твоём случае в useMemomemo надо обернуть сам компонент Replay, а не голый jsx.
    Ответ написан
    2 комментария
  • Как правилось указать тип значений?

    Aetae
    @Aetae Куратор тега JavaScript
    Тлен
    Ошибка в том что файл у вас читается как js, а не как ts. Разберитесь с конфигами.
    Ответ написан
    Комментировать
  • Как решить JSX element type 'LayoutMenu.Category' does not have any construct or call signatures?

    Aetae
    @Aetae Куратор тега JavaScript
    Тлен
    type Extensions = {
      Category: typeof LayoutMenuCategory;
      Item: typeof LayoutMenuItem;
    };

    Иначе оно для ts может быть также и undefined, а undefined - то, что написано в ошибке.
    Ответ написан
  • Как описать OR логику в интерфейсах?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Увы конкретный тип может так работать только при наличии дискриминатора как в варианте 2 или жутких костылей как в варианте 1.

    Однако, если вам это нужно для параметров некоей функции(или react компонента), то в случае передачи аргументом литерала оно может красиво работать с помощью пергрузок:
    interface DefaultProps4 {
        instantPopoup?: boolean;
        // ...
    }
    interface PropsWithCb4 extends DefaultProps4 {
        cb(): void;
    }
    interface PropsWithPath4 extends DefaultProps4 {
        path: string;
    }
    
    
    type Magic = ((arg: PropsWithCb4) => 1) & ((arg: PropsWithPath4) => 2);
    declare const magic: Magic;
    
    // error
    magic({ 
        cb: () => {},
        instantPopoup: true,
        path: "df", 
    });
    
    // 1, no error
    magic({ 
        cb: () => {},
        instantPopoup: true,
    })
    
    // 2, no error
    magic({ 
        instantPopoup: true,
        path: "df", 
    })


    Но только в случае литерала(установка пропсов в jsx - тоже считается литералом), вот так уже не сработает:
    const trololo = {
        cb: () => {},
        instantPopoup: true,
        path: "df",
    }
    magic(trololo); // 1, no error
    Ответ написан
  • Почему код со временем перестает работать, хотя раньше работал отлично?

    Aetae
    @Aetae Куратор тега JavaScript
    Тлен
    Вариантов много.
    Самый вероятный(после банальной ошибки в твоём коде само собой): используется сторонняя библиотека получаемая извне без явной привязки к конкретной версии. Т.е.: обновилась библиотека, поменялся её интерфейс, код перестал работать.
    Самый невероятный: с обновлением браузера изменилась какая-то мелочь в его интерпретации твоего кода. Такое практически исключено, разработчики бразуеров очень сильно пекутся об обратной совместимости.
    Ответ написан
    7 комментариев
  • Как переделать этот код под TypeScript?

    Aetae
    @Aetae Куратор тега JavaScript
    Тлен
    TS тебе предельно понятно написал в чём проблема. Учись читать ошибки.

    Конкретнее же: у тебя не задан тип значения которое может принимать контекст, а выведено самим TS - null(потому что именно такое значение по умолчанию ты передал).
    export const Context = createContext<{
      sidebarIsOpen: boolean;
      toggleSidebar: (value: boolean) => void;
    } | null>(null)
    или лучше
    export const Context = createContext({
      sidebarIsOpen: false,
      toggleSidebar: () => {}
    });
    Ответ написан
    Комментировать