Задать вопрос
  • Нужен ли TypeScript для написания бэкенда на Node.js?

    bingo347
    @bingo347 Куратор тега Node.js
    Crazy on performance...
    Можно ли обойтись обычным js?
    Можно. TypeScript лишь добавляет к JavaScript статическую типизацию в компайл-тайм. После компиляции будет все тот же JS.

    Какие будут плюсы?
    Главный плюс, ИМХО, - скорость разработки за счет подсказок IDE и автодополнения, больше авторефакторингов. Ну и возможность ограничить использование функций/методов от нежелательного использования тоже плюс. А если еще и проектировать доменную модель на типах, то можно сразу видеть, если что-то не сходится, еще до написания логики.

    Не будет ли много лишней писанины по сравнению с чистым js?
    Большинство типов TypeScript способен вывести. Далеко не Хиндли-Милнер конечно, но тоже хорошо. Я пишу больше в ФП стиле, с редкой примесью структурно-процедурного при описании эффектов, так у меня явные указания типов присутствуют только в сигнатурах функций. В самой логике код неотличим от обычного JS, но с хорошей проверкой типов.

    Будет ли сложно хранить скомпилированный js?
    Как и любые другие артефакты сборки, скомпилированный JS хранить не нужно. Компилируйте непосредственно перед выкладыванием на продакшен, а в git храните лишь TS код + настройки компилятора. А в dev среде вообще можно запускаться через модуль ts-node.
    Ответ написан
    Комментировать
  • Проверка значений массива?

    bingo347
    @bingo347 Куратор тега TypeScript
    Crazy on performance...
    type Validator<U extends string, A extends ReadonlyArray<string>> =
      (U extends A[number] ? true : false) extends true ? A : never;
      
    type U = 'foo' | 'bar';
    const arr0 = ['foo'] as const;
    const arr1 = ['bar'] as const;
    const arr2 = ['foo', 'bar'] as const;
    
    type A0 = Validator<U, typeof arr0>; // never
    type A1 = Validator<U, typeof arr1>; // never
    type A2 = Validator<U, typeof arr2>; // readonly ['foo', 'bar']
    
    const _check0: A0 = arr0; // error
    const _check1: A1 = arr1; // error
    const _check2: A2 = arr2;

    https://www.typescriptlang.org/play?#code/C4TwDgpg...
    Ответ написан
    Комментировать
  • Как забрать данные из промиса?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Нет, это не промис, это асинхронная функция, которая отдает свой результат в колбэк, как правило такая функция ничего не возвращает, а значит и await'ить нечего, так как await требует метод then у результата выражения справа.
    Но можно это обернуть в промис:
    async function checkUser(login, password) {
        const ad = new ActiveDirectory(ad_config)
        const auth = await new Promise((resolve, reject) => {
            ad.authenticate(login, password, (err, auth) => {
                if (err) {
                    return reject(err)
                }
                resolve(auth)
            })
        })
        return auth
    }
    Ответ написан
    1 комментарий
  • Типизация функции, возвращающей разные объекты?

    bingo347
    @bingo347 Куратор тега TypeScript
    Crazy on performance...
    const elementSettings = {
      welcome: {
        placeholder: 'Type welcome message...',
        question: '',
        isDescription: false,
        description: '',
        startButtonText: 'Start',
      },
      checkbox: {
        placeholder: 'Type question or statement...',
        question: '',
        isDescription: false,
        description: '',
        options: [] as string[],
        multiple: false,
      }, 
      dropdown: {
        placeholder: 'Type question here...',
        question: '',
        isDescription: false,
        description: '',
        options: [] as string[],
      },
      rating: {
        placeholder: 'Type question...',
        question: '',
        isDescription: false,
        description: '',
        steps: 10,
        defaultRate: 0,
        shape: 'stars',
      },
      text: {
        placeholder: 'Type question...',
        question: '',
        isDescription: false,
        description: '',
        maxLength: 99999,
      }, 
      slider: {
        placeholder: 'Type question...',
        question: '',
        isDescription: false,
        description: '',
        steps: 10,
      }, 
      thanks: {
        placeholder: 'Type message...',
        question: '',
        isDescription: false,
        description: '',
      }
    } as const;
    
    type Editable<T> = { -readonly [P in keyof T]: T[P]; };
    type ElementSettings = typeof elementSettings;
    
    export function getElementSettings<T extends keyof ElementSettings>(type: T): Editable<ElementSettings[T]> {
      if(type in elementSettings) {
        const settings = {...elementSettings[type]};
        if('options' in settings) {
          (settings as {options: string[]}).options = (settings as {options: string[]}).options.slice();
        }
        return settings;
      }
      throw new Error("element type doesn't match!");
    }
    Ответ написан
    Комментировать
  • Как задать дженерик для массива в объекте?

    bingo347
    @bingo347 Куратор тега TypeScript
    Crazy on performance...
    mport React from 'react';
    import { render } from 'react-dom';
    
    type ITableColumn<D extends Record<string, any>> = {
      property: string;
      format?: (value: any, item: D) => React.ReactNode | string | number;
      header?: any;
      footer?: any;
    };
    
    type ITable<T extends Record<string, any>, D extends Record<string, any>> = {
      isLoading?: boolean;
      columns: ITableColumn<D>[];
      rows: Array<T>;
    };
    
    type IContext<D extends Record<string, any>> = {
      rows: any;
      columns: ITableColumn<D>[];
    };
    
    const getColumns = <D extends Record<string, any>>(): ITableColumn<D>[] => [
      {
        property: 'name',
        format: (value, item) => {
          const { lastName } = item;
          return `${value} ${lastName}`;
        },
        header: 'heade',
        footer: 'footer'
      },
      {
        property: 'count',
        header: 'heade',
        footer: 'footer'
      }
    ]
    
    interface AppProps { }
    interface AppState {
      name: string;
    }
    
    const Table:React.FC<ITable> = ({ isLoading, columns, rows }) => {
      return <h1>table</h1>
    }
    
    const App = () => (
      <div>
        <Table 
          columns={getColumns()} 
          rows={[
            { name: 'userName 0', lastName: 'userLastName 0', count: 10 },
            { name: 'userName 1', lastName: 'userLastName 1', count: 20 },
            { name: 'userName 2', lastName: 'userLastName 2', count: 30 },
          ]} 
        />
        <p>Start editing to see some magic happen :)</p>
      </div>
    );
    
    render(<App />, document.getElementById('root'));
    Ответ написан
    2 комментария
  • Как получить все пропсы компонента React по его экземпляру?

    bingo347
    @bingo347 Куратор тега TypeScript
    Crazy on performance...
    import type {ComponentType} from 'react';
    import {Button} from 'react-native';
    
    type InferProps<Component> = Component extends ComponentType<infer Props> ? Props : never;
    
    const MyButton = (props: InferProps<typeof Button>) => {
      return <Button title={props.title} onPress={props.onPress} style={{color:'#fff'}} />
    }
    Ответ написан
    Комментировать
  • Как из элементов массива сделать type в typescript?

    bingo347
    @bingo347 Куратор тега TypeScript
    Crazy on performance...
    const arr = ['a', 'b', 'c'] as const;
    type MyType = (typeof arr)[number];
    Ответ написан
    1 комментарий
  • Функция возвращающая данные полученные из БД, как правильно написать?

    bingo347
    @bingo347 Куратор тега Node.js
    Crazy on performance...
    const select = (query) => new Promise((resolve, reject) => {
      const request = new Request(query);
      request.once('error', reject);
      request.once('done', (rowCount, more, rows) => {
        resolve(rows.map(
          columns => columns.map(
            column => column.value
          )
        ));
      });
      connection.execSql(request);
    });
    Ответ написан
    4 комментария
  • Как отправлять сразу несколько запросов в JavaScript?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Подойдет ли тут многопоточность или я что то путаю?
    В JS нет многопоточности.
    Как это реализовать? С помощью чего?
    Просто отправить несколько запросов сразу. Запросы работают асинхронно и не блокируют поток выполнения.
    Если нужно дождаться сразу несколько ответов, есть Promise.all и Promise.allSettled

    P.S. зачем тащить в приложение тяжелый и ограничивающий функционал axios, когда есть нативный fetch?
    Ответ написан
  • Как мне добавить этот код в header и использовать в другом коде?

    bingo347
    @bingo347
    Crazy on performance...
    Давайте по порядку.
    В представленном примере у нас реализация функции, которая не принимает параметров и возвращает указатель на структуру android_app

    struct android_app * - это возвращаемый функцией тип;
    GetAndroidApp - имя функции;
    Конструкция (void) после имени означает, что функция без аргументов, современные компиляторы позволяют писать просто пустые скобки ();
    В фигурных скобках пишут тело функции, то есть ее реализацию.

    Компиляторы C читают код сверху вниз, использовать можно только то, что объявлено выше. Кроме того некоторые сущности вообще могут компилироваться отдельно и уже после линковаться в 1 исполняемый файл.
    Для этого язык C поддерживает декларации сущностей без их реализации, при условии, что сущность будет реализована ниже или где-то еще, что прилинкуется на сборке.
    Для функций декларацией (так же говорят заголовком) является описание ее сигнатуры, то есть для GetAndroidApp таким заголовком будет:
    // описание структуры android_app должно быть выше заголовка его использующего,
    // иначе он будет невалидным. А вот описание полей (реализация) может быть и ниже
    struct android_app;
    
    struct android_app* GetAndroidApp();


    комментарии говорится что я могу добавить его в Header
    Это значит, что данные сигнатуры можно вынести в заголовочный файл (тот что с расширением .h), это позволит вставить его во множество исходников через директиву препроцессора #include
    Ответ написан
    1 комментарий
  • Как сделать постоянный фоновый Process в C#?

    bingo347
    @bingo347
    Crazy on performance...
    Потому что метод ReadToEnd блокирует тред пока не прочитает весь стрим до конца
    Используйте ReadLineAsync или ReadToEndAsync чтоб читать данные асинхронно.
    Ответ написан
    22 комментария
  • Почему я получаю ошибку TS2322?

    bingo347
    @bingo347 Куратор тега TypeScript
    Crazy on performance...
    routes.map((route: IPrivateRoute | IRoute) => route.access // Здесь ошибка, так как в IRoute нет поля access, а значит нет и в юнионе IPrivateRoute | IRoute
      ? <PrivateRoute key={route.path} {...route}/> // а здесь, так как route.access не является тайп-гвардом, и не смотря на условие, тип по прежнему IPrivateRoute | IRoute
    Ответ написан
    Комментировать
  • Почему код выдаёт неправильный результат?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Когда что-то не понятно, просто распишите каждый шаг, который происходит в программе:
    // запомнили в x значение 0
    x = 0;
    // запомнили в y значение -200
    y = -200;
    
    // тут выражение из нескольких действий
    x = 0 * x + 1 * y
    // 1. вместо переменных подставим значения
    // 0 * 0 + 1 * -200
    // 2. посчитаем умножения
    // 0 + -200
    // 3. посчитаем сложения
    // -200
    // запомним -200 в x
    
    // на этом этапе у нас в x запомнено -200 и в y тоже -200
    
    // с этим проделайте по аналогии
    y = -1 * x + 0 * y
    Ответ написан
    Комментировать
  • Почему игнорируется .append(elem)?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    function render(message) {
      const p = document.createElement("p"); // создали p, его еще нигде нет в DOM, все ok
      p.textContent = message;
      windowChatUser1.append(p); // поместили наш p в windowChatUser1, с этого момента он есть в DOM
      windowChatUser2.append(p); // переместили наш p в windowChatUser2
    }
    логично, что из windowChatUser1 наш p исчез при перемещении в windowChatUser2, так как один элемент не может быть в двух родителях сразу
    Делайте глубокий клон при втором добавлении:windowChatUser2.append(p.cloneNode(true));
    Ответ написан
    1 комментарий
  • Не работает vh, wh, в чем может быть причина?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Слайдер растягивается содержимым, слайдам просто не от чего считать 100% высоты, которые им заданы
    .slider__slide {
      /* изменяем внешний контейнер на viewport величины */
       height: 100vh;
       width: 100vw;
    }
    /* прописываем высоту внутренним контейнерам */
    .slick-list, .slick-track {
      height: 100%;
    }
    Ответ написан
    Комментировать
  • Как можно корректно написать асинхронный метод у объекта в typescript с дженериком?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    В дополнение к Aetae - дженерик здесь тоже не нужен
    Да, парсинг JSON возвращает any (по историческим причинам) и его вот таким дженериком можно легко кастануть в любой тип. Только зачем вообще использовать TypeScript если мы вечно его затыкаем своей правотой?
    Даже если данные приходят с нашего сервера, и мы точно знаем их тип - их нужно проверять, ибо нет гарантии, что никто не ошибся на бэке, что мы не ошиблись в описании типа в который кастуем.
    Поэтому должен быть тип unknown, чтоб TypeScript требовал все проверить перед использованием:
    const ApiServiceModule = {
      get: (url: string): Promise<unknown> => fetch(url)
        .then(response => response.json())
        .catch(err => console.error(err))
    }
    Ответ написан
    Комментировать
  • Как сделать условие JavaScript с помощью setinterval?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Ошибка в точке запятой после ifif (document.URL.indexOf("/testurl/") != -1);if обрабатывает пустую операцию, все что дальше уже вне if

    Поэтому всегда заключайте тело условий и циклов в фигурные скобки.

    Нормальный вариант уже предложен Absolute138

    Но остается вопрос, зачем здесь вообще интервал?
    Ответ написан
    2 комментария
  • Функция валидации которая выбрасывает исключения?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Возвращайте Result, Ok при успешной валидации или Err с ошибкой при неудачной, а после соединяете все ошибки и выводите пользователю информацию
    При throw приложение падает, Вы конечно можете поймать throw через try-catch, но он приведет Вас к полному хаосу в Вашем коде и нестабильному приложению. А кроме того, нет возможности обработать все валидации за раз, если первая упадет, об остальных юзер узнает только когда исправит данные, как думаете, на какой раз он пошлет Ваше приложение?
    Ответ написан
  • Как типизировать dispatch функции?

    bingo347
    @bingo347 Куратор тега TypeScript
    Crazy on performance...
    сделайте вот так: setError(e.message)(dispatch) вместо
    dispatch(setError(e.message)) // здесь возникает ошибка, т.к. setError возвращает функцию
    и все будет правильно сразу
    Ответ написан
    Комментировать
  • Как из массива, представляющего дерево, извлечь корни?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    // проиндексируем по ключам
    const [rootIndex, idIndex] = array.reduce(([roots, ids], obj) => {
      (roots[obj.root_id] ??= []).push(obj);
      ids[obj.id] = obj;
      return [roots, ids];
    }, [{}, {}]);
    // и найдем по нему нужные объекты:
    const objectsWithoutExistingParent = Object.keys(rootIndex).filter(key => !idIndex.hasOwnProperty(key)).flatMap(key => rootIndex[key]);
    console.log(objectsWithoutExistingParent);

    Конечно чуть больше кода, чем у 0xD34F, зато с линейной сложностью
    P.S. а я все жду, когда 0xD34F начнет впаривать факториальную сложность новичкам, а то с квадратичной веб конечно тормозит, но не такими темпами...
    Ответ написан
    Комментировать