Ответы пользователя по тегу TypeScript
  • Из-за чего появляется ошибка по classList?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Используй addEventListener.
    Ответ написан
    Комментировать
  • Почему Angular компонент не рендерится?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    AdBlock попробуй отключить.)
    Ответ написан
    Комментировать
  • Как исключить определенный класс из типа в Typescript?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    В typescript структурная тпизация. Ему похрен какой класс породил объект. Если порождённый объект структурно совпадает с сигнатурой(сигнатуры всех свойств и методов совпадают), то такой объект проходит по условию:
    class Foo {
      a!: number;
      b!: number;
    }
    function bar(arg:Foo) {};
    const randomObj = {a:1, b:2, c:5};
    
    bar(randomObj); // ok


    Потому ты не можешь "исключить определенный класс", как в принципе не можешь и ограничить "определенным классом", любые ограничения могут быть лишь структурными.
    Ты можешь запретить объект с определённым набором свойств на вход, но это ограничит не только "определенный класс", но и любые другие классы порождающие объект с подобным набором полей.

    Костыль - добавить нужному классу пустое приватное свойство и ограничивать по нему.
    Ответ написан
    Комментировать
  • Как обязать typescript допускать выполнения кода только в том случае, если два типа строго равны друг другу?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Ответ: не использовать typescript.
    Структурная типизация - суть typescript. Ты можешь нагугуглить всякие мерзкие костыли, но они не панацея и подведут в самый ответственный момент.
    Ответ написан
  • Как не подключать библиотеку и не получить ошибку?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    import type LibnameType from 'libname';
    
    declare global {
      const libname: typeof LibnameType;
    }
    Ответ написан
    Комментировать
  • Как указать Typescript понимать index.tsx по дефолту?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    moduleResolution: node попробуй поставить, хотя с по идее с"module": "es6", он по умолчанию такой должен быть...
    Также можно попробовать указать baseUrl.

    P.S. Возможно вообще просто надо ребутнуь\сбросить индекс в IDE, порой оно глючит.
    Ответ написан
    Комментировать
  • Как динамически добавить метод в класс, внутри этого же класса?

    Aetae
    @Aetae Куратор тега JavaScript
    Тлен
    В typescript нельзя изменять существующий класс. Класс - законченная сущность. Конец.

    С помощью наследования ты можешь добавить новые методы в новый класс-наследник.

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

    Aetae
    @Aetae Куратор тега JavaScript
    Тлен
    Ну, тебе прямым текстом сказано: match может вернуть null и тогда произойдёт ошибка во время исполнения.

    Либо так:
    const [a, b, c, d, f, g= ''] = value.match(/\d+/g) || [];
    Либо, если ты на 146% уверен, что match обязательно что-нибудь найдёт:
    const [a, b, c, d, f, g= ''] = value.match(/\d+/g) as string[];
    Ответ написан
    Комментировать
  • Как использовать алиасы путей tsconfig?

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

    P.S.
    Иначе зачем вообще нужны алиасы в ts?

    На самом деле фичу paths запилили, чтобы отразить поведение модных сборщиков, типа webpack, а не наоборот. Т.е. предполагается, что paths используются только когда уже есть сборщик который осуществляет всю логику, а не как первичный источник конфигурации.
    Ответ написан
  • Как работать с функциями высшего порядка?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Расширять, очевидно, с помощью ключевого слова extends.
    Всё остальное - исключительно хаки и костыли. Typescript предполагает, что класс не должен изменяться "на лету" никоим образом.
    Ответ написан
  • Возможен ли условный тип исходя из статического свойства класса в TypeScript?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    lightalex, максимум можно изобразить что-то такое:
    class A {
      static bool: boolean = true;
    }
    class B extends A {
      static readonly bool = true;
    }
    class C extends A {
      static readonly bool = false;
    }
    function func<T extends typeof A, P = T['bool'] extends true ? number : string>(param: P) { } 
    
    func<typeof B>(123); //ok
    func<typeof B>('random string'); //not ok
    func<typeof C>(123); //not ok
    func<typeof C>('random string'); //ok

    Но если параметр bool может меняться во время исполнения - тайпскрипт никак не может знать его значение во время компиляции.
    Ответ написан
    1 комментарий
  • Типизация функции, возвращающей разные объекты?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Проще всего сделать так, ts сам подберёт типы:
    const elementDefaults = {
      '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: '',
      }
    }
    
    
    export function getElementSettings<E extends keyof typeof elementTypes>(type: E) {
      if(!(type in elementDefaults)) throw new Error("element type doesn't match!");
      return elementDefaults[type];
    }

    Но если хочется по правилам, то как-то так:
    type ElementSetting = {
      placeholder: string;
      question: string;
      isDescription: boolean;
      description: string;
    }
    
    type ElementSettings = {
      welcome: ElementSetting & {
        startButtonText: string;
      },
      checkbox: ElementSetting & {
        options: string[];
        multiple: boolean;
      },
      dropdown: ElementSetting & {
        options: string[];
      },
      rating: ElementSetting & {
        steps: number;
        defaultRate: number;
        shape: string;
      },
      text: ElementSetting & {
        maxLength: number;
      },
      slider: ElementSetting & {
        steps: number;
      },
      thanks: ElementSetting
    }
    
    const elementDefaults: ElementSettings = {
      'welcome': {
        placeholder: 'Type welcome message...',
        question: '',
        isDescription: false,
        description: '',
        startButtonText: 'Start',
      },
      'checkbox': {
        placeholder: 'Type question or statement...',
        question: '',
        isDescription: false,
        description: '',
        options: [],
        multiple: false,
      },
      'dropdown': {
        placeholder: 'Type question here...',
        question: '',
        isDescription: false,
        description: '',
        options: [],
      },
      '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: '',
      }
    }
    
    
    export function getElementSettings<E extends keyof ElementSettings>(type: E): ElementSettings[E] {
      if(!(type in elementDefaults)) throw new Error("element type doesn't match!");
      return elementDefaults[type];
    }
    Ответ написан
    1 комментарий
  • Как правильно прописать тип аргумента, чтобы были видны статичные свойства класса?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    class A {
      static b = 123;
    }
    function f(cls: typeof A) {
      console.log(cls.b); 
    }
    Ответ написан
    Комментировать
  • Почему скрипт запуска проекта из package.json падает с ошибкой?

    Aetae
    @Aetae Куратор тега JavaScript
    Тлен
    Винда не считает ' кавычками и кидает их как часть параметра.
    Экранировать чтоб оно работало на всех ОС - не так просто, а результат - уродлив, так что рекомендуется просто указать параметры для перезаписи под ключом ts-node в tsconfig.json:
    {
      "ts-node": {
        "compilerOptions": {
          "module": "CommonJS"
        }
      },
      ...
    }
    Ответ написан
    1 комментарий
  • Как исправить ошибку Property 'item' does not exist on type 'Record'?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Во-первых: как верно заметил YavaDev: classes[item].
    Во-вторых: только вручную, на свой страх и риск:
    for(let item in classes) {
        classes[item as keyof typeof classes] = 'page'+item
    }
    В typescript специально не добавили автоматическую типизацию ключей оставив просто string, так как из-за его структурной природы нельзя наверняка сказать, есть ли в полученном объекте(или его прототипе) ещё какие-то ключи, кроме тех, что указаны в его типе, и, соответственно, нельзя быть уверенным, что ничего не сломается.
    Ответ написан
    Комментировать
  • Фильтрация вложенных данных React?

    Aetae
    @Aetae Куратор тега JavaScript
    Тлен
    1. В любой строке встречается пустая строка, по этому такой поиск выдаёт все значения.
    2. map складывает в выходной массив результат переданной функции. Поскольку она у вас возвращает отфильтрованный массив items, то в итоге у вас получается массив массивов items. Если вам нужно, чтоб возвращались категории - возвращайте категории.

    Ну и дважды одну и ту же работу делать не надо, можно обойтись одним reduce:
    сonst filterData = filter(arr, input.value);
    
    interface Category {
      category: string;
      list: Array<{
        item: string;
      }>;
    }
    
    function filter<T extends Category>(data: T[], value: string): T[] {
      if (!value) return data.slice(); // или [] если при пустом value нужен пустой массив
      value = value.toLowerCase();
      
      return data.reduce((result, category) => {
        if(category.category.toLowerCase().includes(value)) {
          result.push(category);
        } else {
          const list = category.list.filter(({ item }) => item.toLowerCase().includes(value));
          if (list.length) {
            result.push({
              ...category,
              list
            });
          }
        }
        return result;
      }, [] as T[])
    }
    Ответ написан
    Комментировать
  • Как можно корректно написать асинхронный метод у объекта в typescript с дженериком?

    Aetae
    @Aetae Куратор тега JavaScript
    Тлен
    Что именно ты хочешь сократить, вроде ж дальше некуда: один тип на вход - один на выход?

    Ну можешь убрать async и await, они здесь не нужны:
    const ApiServiceModule = {
      get: <T>(url: string): Promise<T> => fetch(url)
        .then(response => response.json())
        .catch(err => console.error(err))
    }
    async/await всего лишь сахар над Promise и в данном случае ничего не делают, т.к fetch и так возвращает Promise.

    P.S. Ну и методом я бы это не назвал, это свойство с функцией. Метод имеет доступ к this.
    Ответ написан
    Комментировать
  • Реален ли такой дженерик в TypeScript?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Вот так с указанием на аргументы:
    function wrapper<T extends { start(...args: unknown[]): unknown }>(target: { new(): T }, ...args: Parameters<T['start']>): T {
      let instance = new target();
      instance.start(...args);
      return instance;
    }
    
    
    class RandomClass {
      start(arg1: string, arg2: number) { /* ... */ }
    }
    let instance = wrapper(RandomClass, 'Hello, world!', 777); /// все ок
    let instance2 = wrapper(RandomClass, 777); /// ошибка
    Ответ написан
    Комментировать
  • TSlinter ругается на символ?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Если не знаете английского языка - выкиньте линтер. Какая вам польза от того, что он вам пишет "какие-то" сообщения, которые вы не способны прочитать?
    Ответ написан
    Комментировать
  • Как типизировать массив ключей интерфейса?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Тут есть несколько решений.
    Например:
    type TupleUnion<U extends string, R extends string[] = []> = {
    	[S in U]: Exclude<U, S> extends never ? [...R, S] : TupleUnion<Exclude<U, S>, [...R, S]>;
    }[U] & string[];
    
    interface Interface {
      foo: boolean;
      bar: string;
      baz: object
    }
    
    type Keys = TupleUnion<keyof Interface>; 
    
    let keys: Keys;
    
    keys = ['foo', 'bar', 'baz']; // OK все ключи указаны
    keys = ['foo']; // NOT OK указаны не все ключи
    keys = ['foo', 'bar', 'another bar']; // NOT OK один из ключей не совпадает

    Но в реальном проекте их использовать крайне не рекомендуется - они сожрут тебе всю память и весь процессор, если ключей будет побольше чем парочка.
    Ответ написан
    Комментировать