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

    Aetae
    @Aetae Куратор тега JavaScript
    Тлен
    Ну по enter у тебя же что-то происходит? Вот перед основным кодом триггерни blur руками:
    document.activeElement.dispatchEvent(new Event('blur'));


    Это конечно костыль, и по логике тебе надо написать кастомную обработку варианта с onChange, но и так, наверное, сойдёт.
    Ответ написан
    Комментировать
  • Vue3, как сделать задержку внутри computed?

    Aetae
    @Aetae Куратор тега JavaScript
    Тлен
    Условно как-то так:
    const betsArr = ref();
    watch(<то что было в computed>, debounce((value) => betsArr.value = value, 1000));
    Ответ написан
    Комментировать
  • Как изменить, а не перезаписасать тип у вложенных объектов?

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

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Т.е. по сути у тебя (определяемый в рантайме) инстанс неизвестного класса, абсолютно рандомного, раз даже сигнатуры схожих методов не совпадают.

    Ну тогда какбэ остаётся только проверять руками, что за инстанс имеем перед использованием. Типа if (instance instanceof Animal) { ... }, как иначе то? Как-то ты же сейчас проверяешь какой метод вызвать specificAnimalMethod или specificHumanMethod?
    Ответ написан
  • Почему typescript не видит перегрузку?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    На самом деле вопрос в IDE. Вот тут нормально всё подсказывает например.

    Другой вопрос, что при заданном так типе ты можешь писать и link и children одновременно. Чтоб такого делать typescript не давал нужно поле-дискриминатор, типа:
    export type NavDataItem =
      | {
          type: 'a',
          name: string;
          link: string;
        }
      | {
          type: 'b',
          name: string;
          children: NavDataItem[];
        };
    Ответ написан
    Комментировать
  • Почему я получаю undefined?

    Aetae
    @Aetae Куратор тега JavaScript
    Тлен
    Ну в комменте уже ответили, что приходит тебе не совсем то, что ты там в типе написал.
    Рекомендую не писать руками интерфейсы для готового json, лучше тыкнуть в консоли на ответе "Copy object" и вставь в любой конвертер, который гуглится по "json to ts", например https://app.quicktype.io/. Так ты точно не ошибёшься, а потом уже можешь уточнить тип руками.

    В идеале, конечно, неплохо бы каждый ответ от сервера считать unknown и прогонять через тайпгард, проверяя руками, что он соответствует типу, но это не частая практика, увы.
    Ответ написан
  • Как правильно задать Types для объектов где есть несколько типиов "контента"?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    export interface Post {
      title: string;
      content: Content[]; // мы ждём тут массив, а не кортеж из одного элемента
    }
    
    export type TContentType = "text" | "video" | "header" | "code" | "images" | "remark" | "materials";
    
    // базовый интерфейс, чисто для надёжности, никуда не экспортируем
    interface IContentBase {
      type: TContentType
    }
    
    export interface ITextContent extends IContentBase {
      type: "text";
      value: string;
    }
    
    export interface IVideoContent extends IContentBase {
      type: "video";
      url: string;
    }
    
    // ...
    
    export interface IOtherContent extends IContentBase {
      type: "header" | "code" | "images" | "remark" | "materials";
    }
    
    // делаем union с type как discriminator field
    export type Content = ITextContent |  IVideoContent | IOtherContent;
    
    const items: Post = {
      title: "foo bar",
      content: [
        {type: "text", value: "lorem 1"},
        {type: "video", url: "lorem 2"},
        {type: "text", value: "lorem 3"}
        // ...
      ]
    };
    
    // используем тайпгард, тайпскрипт недостаточно умный, чтоб вывести Extract<Content, { type: "text" }> в таких случаях
    const onlyTextType: ITextContent[] = items.content.filter((it): it is ITextContent => it.type === "text");
    // ...
    Ответ написан
    Комментировать
  • Как получить переменную 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 Куратор тега JavaScript
    Тлен
    Ну потому что 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 Куратор тега JavaScript
    Тлен
    А ты для начала придумай синтаксис для этого, который бы не вступал в прямой кофликт с 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) => { ... }
    Ответ написан