Ответы пользователя по тегу TypeScript
  • Как получить переменную php в typeScript?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    1. PHP испоняется на сервере.
    2. Javascript исполняется на клинете.
    3. Typescript исполняется у тебя на машине(\в CICD) при компиляции в javascript.

    Исходя из этого ts и php никак напрямую не связаны.

    Ты можешь либо делать из кода ajax запрос на сервер, и получать в ответ константы.
    Либо ты можешь просто подключать через <script> php файл который сгенерирует простой скрипт устанавливавший заданные константы и в js, условно так:
    header("Content-Type: application/x-javascript");
    
    define("CONSTANT", 1);
    
    echo 'Object.assign(window,' . json_encode(
    	get_defined_constants(true)['user']
    ) . ');';
    Ответ написан
    Комментировать
  • Как написать функцию с возвращаемым значением типа string, возвращающую одно из полей json'а, пришедшее с запросом axios?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Мужик, async/await - это просто сахар над Promise. Любая async функция возвращает Promise по определению, любой await этот Promise разрешает.
    async function setLegalLevel(): Promise<string> {
      ...
      await axios.post
      ...
    }
    ...
    const val: string = await setLegalLevel();
    Ответ написан
    Комментировать
  • Как обратиться к свойству объекта в typescript, если оно есть только в одном из нескольких возможных типов этого объекта?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Как и во всех подобных случаях - проверить какой конкретно у тебя там тип перед использованием:
    declare const a: {a: 1, b: 2} | {a: 1};
    
    if ('b' in a) { // ts тут сужает тип до {a: 1, b: 2}
      console.log(a.b);
    }

    P.S. Ты нарушаешь правило 3.8, не делай так.

    Ответ написан
    Комментировать
  • Типизация большого объекта в Typescript?

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

    Любой тип который вы присваиваете приходящему в будущем ответу является по сути обманом TS'а, потому что вы не можете гарантировать, что с сервера не прилетит что-то другое.

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

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Ну потому что extend - это "расширение", и главное совместимость, м?

    В данном случае любой UserInfo обратно совместим с BaseUserInfo, т.к. для BaseUserInfo.getState() возвращаемое значение имеет тип void (не путать с undefined), который никак не может быть использован (сам ts не даст).
    abstract class BaseUserInfo {
      abstract getState(): void;
    }
    
    class UserInfo extends BaseUserInfo { 
      override getState = (): number => 1;
    }
    
    function useInfo(info: BaseUserInfo) {
      // An expression of type 'void' cannot be tested for truthiness.(1345)
      if (info.getState()) { // не получится так сделать и всё сломать
        console.log('never')
      }
    }
    Ответ написан
    Комментировать
  • Как правильно написать enum в React Typescript?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Ну какбэ очевидно, что в item.deviceType у тебя строка, а не DeviceType. Проверь что у тебя там в item.
    Ответ написан
  • Как типизировать значение?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Если ты не указываешь при useState тип стейта руками, то он выводится автоматически.

    useState([null, null]); - ts выведет тут тип null[], то есть массив null, про Date он никак догадаться не может. Следует указать явно: useState<Array<Date | null>>([null, null]);
    Ответ написан
    3 комментария
  • Как правильно записать проверку контекста next-redux-wrapper?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Глубоко не вникал, но наверное тут логично испрользовать тайп гарды:
    // какая-то проверка достаточная чтобы сказать, что у нас тут NextPageContext;
    const isNextPageContext = (ctx: unknown): ctx is NextPageContext => false; 
    // аналогично для AppContext
    const isAppContext = (ctx: unknown): ctx is AppContext => false; 
    
    const baseQuery = fetchBaseQuery({
      baseUrl: 'http://localhost:7777/api/auth',
      prepareHeaders: (headers, { extra }) => {
        let req;
    
        if (isNextPageContext(extra)) {
          req = extra.req;
        } else if (isAppContext(extra)) {
          req = extra.ctx?.req;
        }
    
        if (req) {
          headers.set('Cookie', req.headers.cookie || '');
        }
    
        return headers;
      },
      credentials: 'include',
    });
    Ответ написан
    Комментировать
  • Как сделать возврат последнего успешного значения и retry вместе с delay в случае ошибки?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Как-то так (не проверял):
    interface CreateConnectionOptions extends ConnectOptions {
      retryCount?: number;
      retryDelay?: number;
    }
    
    function createConnection(uri: string, {
      retryCount = 6,
      retryDelay = 1000,
      ...mongooseConnectOptions
    }: CreateConnectionOptions = {}): Observable<Connection> {
      let connection$ = defer(() => mongoose.createConnection(uri, mongooseConnectOptions).asPromise());
      
      if (retryCount > 0) {
        connection$ = connection$.pipe(retry({
          count: retryCount,
          delay: retryDelay
        }));
      }
      
      return connection$.pipe(shareReplay(1));
    }
    Ответ написан
    Комментировать
  • Как типизировать огромный объект в typescript?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Если объект уже есть, то его самого можно использовать как тип.
    const obj = { ... }; 
    type Obj = typeof obj;

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

    Если поля поддаются какой-то логике, то с использованием литералов можно сделать компактный тип.
    Ответ написан
    Комментировать
  • Возможно ли реализовать более изящную типизацию объектов и деструктивное присваивание?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    А ты для начала придумай синтаксис для этого, который бы не вступал в прямой кофликт с JS и при этом был интуитивен.)
    Вот тут на тему много копий сломано, но, ИМХО, нет нормальных достойных релиза вариантов.)
    Ответ написан
    Комментировать
  • Как в TypeScript, добавлять свойство по условию?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Нужно больше чёткости. Какой ещё бывает view кроме labled?
    Через интерфейсы это сделать нельзя - можно через union типов, но обязательно должно быть поле-дискриминатор, различное для каждого случая.

    Если такого поля нет - конкретный тип сделать нельзя, однако судя по приставке Props, можно предположить, что это какие-то props какого-то React компонента, тогда этого можно добиться с помощью перегрузки:
    export interface ModalProps extends CuiModalProps {
        children: ReactElement | ReactElement[]
        setterClosePopup: Dispatch<SetStateAction<boolean>>
        namePopup?: string
        isOpen?: boolean
        withBorder?: boolean
        className?: string
    }
    export interface ModalPropsLabled extends ModalProps {
        view: 'labeled'
        label: string
    }
    
    export const Component: ((pros: ModalProps) => ReactNode) & ((pros: ModalPropsLabled) => ReactNode) = (pros: ModalProps | ModalPropsLabled) => { ... }
    Ответ написан
  • Стоит ли вносить константы в класс?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Константы в классе - нормальная практика, однако они должны быть static, нечего их в каждом инстансе дублировать.
    Ответ написан
    Комментировать
  • Как правльно использовать TS в монорепе?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Все интерфейсы что должны быть публичными - должны быть экспортированы в корне @company/core, точно также как и все модули.
    Ответ написан
    1 комментарий
  • В чем причина 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.
    Ответ написан
    Комментировать