Ответы пользователя по тегу TypeScript
  • В чем причина ts ошибки при передаче пропсов в компонент?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Где-то среди >260 свойств из React.ComponentPropsWithRef<'select'> находится свойство, которое дженерик Option в Select устанавливает как string | number с большим приоритетом, чем то что ты кладёшь собственно в Options. Можешь поискать сам убирая по одному или сравнивая с декларацией для Select.

    Но в принципе решение просто выкинуть React.ComponentPropsWithRef<'select'>, т.к. ты расширяешь не нативный select, а react-select.
    import Select, { Props } from 'react-select';
    
    interface ISelectProps extends Props<OptionType> {
        caption?: string;
        disabled?: boolean
    }
    Ответ написан
  • Как лучше сделать экспорт класса, чтобы вызывать его как функцию?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Вам лень писать new? Имхо, это перебор. Не отвалятся у вас руки три лишних символа написать, и это будет куда нагляднее чем непонятные излишние функции.

    Но рас так хочется, то тип для твоей функции таков:
    function exportConstruct<P extends any[], T>(classFromExport: { new (...args: P): T; }): 
    (...args: P) => T {
      return (...args) => new classFromExport(...args);
    }

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

    Если можешь использовать Proxy то можно просто сделать класс вызываемым:
    function exportCallable<T extends { new (...args: any[]): any; }>(classFromExport: T) {
      return new Proxy(classFromExport, {
        apply(ctor, _, args) {
          return new ctor(...args);
        }
      }) as T & ((...args: ConstructorParameters<T>) => InstanceType<T>);
    }
    
    const Lol = exportCallable(class Lol extends BaseLol {
      constructor(public name: string) {
        super();
        this.name = name.toUpperCase();
      }
    });
    
    Lol('qwe');


    Либо ты можешь просто добавть статический метод, который будет делать то же самое:
    abstract class Newable {
      static new<P extends any[], T>(this: { new (...args: P): T; }, ...args: P): T { 
        return (new this(...args)) as T
      }
    }
    
    class BaseLol extends Newable {  /* ... */ }
    
    class Lol extends BaseLol {
      constructor(public name: string) {
        super();
        this.name = name.toUpperCase();
      }
    }
    
    Lol.new('qwe');
    Ответ написан
  • Как указать в TypeScript интерфейсе, что в массиве могут содержаться много однотипных объектов?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    [ {title: string, cardList: []} ] - это не массив, заполняемый значениями типа {title: string, cardList: []}, это кортеж из одного значения данного типа.
    Массив обозначается так Array<{title: string, cardList: []}> или так {title: string, cardList: []}[].
    Кортеж используется когда нужно конкретное количество значений конкретного тип на конкретных позициях.
    Ответ написан
    1 комментарий
  • Почему не получается создать тип Object[] в typescript?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    В данном случае T значит любой конкретный тип который extends Object[].
    например new A<[{c: 3}]>() - абсолютно валидно, при этом в public B уже не может быть того что ты туда положил.
    Ответ написан
    Комментировать
  • Как переназначить функцию console.log в nodejs?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Вынеси свою подмену в отдельный модуль и делай его require\import ДО импорта той библиотеки.
    Правда не факт что либа использует именно console.log, а не stdout напрямую.
    Ответ написан
    Комментировать
  • Как правильно затипизировать данный кусок кода?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Если не используете Node.js то просто исключите типы для неё из конфига TS.
    Тогда у вас setTimeout будет возвращать простой number, а clearTimeout будет принимать number | undefined. И никаких проблем.)

    Если же код ноды по каким-то причинам у вас идёт вперемешку со фронтовым кодом, то для фронтовых таймеров можете писать явно window.setTimeout и window.clearTimeout.
    Ответ написан
    Комментировать
  • TypeScript. Как сделать оверлоад объекта стрелочной функции?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    ТС недостаточно умный для этого. Решает он так, потому что когда ты делаешь SomeType extends BaseType для аргумента функции, внутри функции значение этого аргумента просто BaseType и автоматический вывод исходит из этого. Тут либо добавлять руками оверлоады и на враппер, или пробовать писать головоломный тип, или обойтись без оверлоадов явными условиями типа:
    type MyFuncAs =<T extends boolean> (obj?: Obj<T>) => T extends false ? number : string;
    Ответ написан
    1 комментарий
  • Vetur отключить предуприждение стилистики?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    В каком-ниюудь модуле укажи:
    declare global {
      const VUE_APP_WS_URL: string | undefined;
    }

    В тайпскрит всё должно быть типизированнно. Ты не можешь просто с потолка брать какие-то переменные.
    Ответ написан
    Комментировать
  • Где размещать тесно связанные типы typescript?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Не слушай Василий Банников, плодить копипаст-типы точно не надо.

    А по размещению типов точно такая же логика как с обычными модулями. Так что абсолютно нормально импортировать связанные типы из связанного модуля. Все теории и паттерны проектирования применяются и тут.

    По хорошему конечно стоит придерживаться SOLID или чего-то подобного.
    Т.е. в Grid сделать тип IGridItemProps с теми свойствами которые точно нужны для работы Grid, а в GridItem наследовать от него уже конкретную реализацию
    interface GridItemProps extends IGridItemProps { ... }
    . Однако это нужно только если теоретически могут появиться ещё GridItemSuper и GrigItemNice, если же такого быть не может и модули(компоненты) сами по себе тесно связны, то заморачиваться не стоит.
    Ответ написан
  • Как реализуется enum в JS из Typescript?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Потому что enum в typescript может мержиться:
    Валидный код:
    enum Membership {
      Simple,
      Standart,
      Premium
    }
    
    enum Membership {
      SimpleX = 99
    }

    Почему компилятор не собирает его воедино, если такие штуки тока на этапе компиляции работают - я хз, но наверное есть причины.
    Ответ написан
    3 комментария
  • Как проверять существуемость объекта в dispatch?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Как уже сказал Lynn «Кофеман»: чтоб typescript не ругался на null ты должен сделать так, чтобы там не было null. Довольно очевидно, да.

    На практике надо сделать либо так:
    const data = useSelector(state => state.DataState.Data) ?? defaultData;
    Либо так:
    if (favorite && data) {

    Ну или ещё как, на твой вкус.
    Ответ написан
  • Как реализовать union типы для action?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Также как и всегда, в этом суть типов.
    Переданное значение может быть или одного типа или другого. И пока ты явно не проверишь через if какого же именно типа прилетело значение - использовать его нельзя.
    Ответ написан
  • Как использовать состояния внутри UI компонента?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Ты должен делать с ним <TestBlock/> или React.createElement(TestBlock), а ты где-то делаешь просто TestBlock().
    Ответ написан
  • Как можно написать декоратор, который бы указанную функцию оборачивал бы в определённый код?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Условно так:
    const RunOutsideAngular = (target: any, memberName: string) => {
      const method = target[memberName];
      return Object.defineProperty(target, memberName, {
        writable: true,
        configurable: true,
        value(...args: any[]) {
            return this.ngZone.runOutsideAngular(method.bind(this, ...args))
        } 
      });
    };
    
    const RunOutsideAngularAll = (constructor: Function) => { 
        const keys = new Set<string>(); 
        let proto = constructor.prototype;
    
        do {
            if(proto === Object.prototype) break;
    
            Object.getOwnPropertyNames(proto).forEach(
                key => typeof proto[key] === 'function' 
                    && key !== 'constructor'
                    && keys.add(key)
            );
        } while (
            proto = Object.getPrototypeOf(proto)
        );
    
        keys.forEach(key => RunOutsideAngular(constructor.prototype, key));
    }
    
    class SomeClass {
        @RunOutsideAngular
        myFunc() {
            mycode.....
        }
    }
    
    // или
    
    @RunOutsideAngularAll
    class SomeClass {
        myFunc() {
            mycode.....
        }
    }


    RunOutsideAngular - по-хорошему надо типизировать дженериком под ангуляр.
    RunOutsideAngularAll - обрабатывает все методы и функции, в т.ч. унаследованные, можно упростить чтоб работал только с методами текущего класса.
    Ответ написан
    1 комментарий
  • Ошибка конфигурации typescript, как исправить?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    В ошибке всё написано. Прямой импорт из .json выводит недостаточно строгий тип. Метод ожидает что type будет строго одно из "direct" | "fanout" | "headers" | "topic", а получает просто string.

    Можно сделать так:
    return (await this.rascal.create(RascalConfig as BrokerConfig))
    Но это чревато ошибками в самом конфиге.

    Единственное на данный момент надёжное решение(пока не добавят эту фичу) - держать конфиг в .ts файле в виде:
    const RascalConfig: BrokerConfig = { ... }
    или
    const RascalConfig = { ... } as const

    Ну или написать простенький генератор соответствующего .d.ts к каждому .json.
    Ответ написан
    1 комментарий
  • Как подружить vue 3 options API на typescript с vue-router?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    export default defineComponent({ ... })
    Ответ написан
    3 комментария
  • Как замаппить json в массив объектов?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Просто:
    let routes = await axios(...)
    .then((response: AxiosResponse<Route[]>) => response.data)
    .catch(console.log);
    Нет смысла гонять из пустого в порожнее.

    Только учитывай - все проверки типов и моделей typescript делает на этапе компиляции. На этапе исполнения никакого typescript не существует, потому когда приходит ответ с сервера нет никаких гарантий что он соответствует модели, и typescript не сможет никак отловить если это не так. Если нужны какие-то проверки - их надо писать самому руками или с помощью соответствующих либ.
    Ответ написан
    1 комментарий
  • Ошибка при создании приложения React?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Подозреваю # в пути лишний.
    Ответ написан
    Комментировать
  • Как можно улучшить код?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Про паттерны-фигаторны ничего не скажу, а вот то что метод начинающийся на validate не должен ничего никуда писать - это факт.)
    Ответ написан
    Комментировать
  • Почему я не могу импортировать модуль faker?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Чтоб пакеты грузились из node_modules по имени, скрипт надо запускать в node(т.е. на сервере), либо собирать его сборщиком(который сам заберёт по имени и запакует в скрипт).
    Если же хочешь использовать их напрямую в браузере через type moule - придётся тебе руками явно указывать конкретные пути до конкретных фалов скрипта. package.json и всё что с ним связано - это экосистема node. Из-за удобства и универсальности она принята за стандарт для всей разработки фронта, но браузер об этом ничего не знает.
    Ответ написан
    3 комментария