Ответы пользователя по тегу TypeScript
  • Не считаете ли вы Utility types code smell'ом?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Всё зависит от того как вы походите к typescript: если он для вас является отдельным языком и вы пришли к нему от java\c# - то тогда действительно стоит всего этого "ужаса" избегать и писать "строго"; если же typescript для вас - надстройка над javascript, цель которой упростить написание кода и сократить количество шибок, сохранив "гибкость" и "вариативность" javascript - то стоит использовать всё что есть.)
    Ответ написан
    Комментировать
  • [TypeScript] Можно ли создать тип из ключей объекта?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Можно, если им явно не указать тип Args, но тогда вы теряете предварительную проверку, увы:
    let a1 = {
        channelID: {
            RegExp: ["\\d+", true],
            description: "d1"
        },
        content: {
            RegExp: [".+", true],
            description: "d2"
        }
    };
    type T1 = {[K in keyof typeof a1]: string}


    Чтобы сохранить проверку - придётся воспользоваться дополнительной бессмысленной функцией для уточнения типа:
    type Args = {
        [key: string]: {
            RegExp: [string, boolean],
            description: string
        }
    }
    function createArgs<T extends Args>(args: T): T {
        return args;
    }
    
    type TStringKeys<T extends Args> = {[K in keyof T]: string};
    
    
    let a1 = createArgs({
        channelID: {
            RegExp: ["\\d+", true],
            description: "d1"
        },
        content: {
            RegExp: [".+", true],
            description: "d2"
        }
    });
    
    type T1 = TStringKeys<typeof a1>
    К сожалению на текущий момент(ts4.2.3) избавиться от функции-обёртки не получится.
    Ответ написан
    1 комментарий
  • Как правильно выполнить типизацию функции трансформации данных?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    interface IOrder {
        date: string,
        docTypesName: string,
        docId: number,
        image: string,
        name: string,
        price: number,
        quantity: number,
        removed: number,
    }
    
    interface  IProduct {
        image: string,
        name: string,
        price: number,
        quantity: number,
    }
    
    interface IDocument {
        date: string,
        docId: number,
        docTypesName: string,
        products: IProduct[],
    }
    
    interface IElement {
        date: string,
        documents: IDocument[]
    }
    
    interface IElementMap {
        date: string,
        documents: Record<string, IDocument>
    }
    
    type IResultMap = Record<string, IElementMap>;
    
    function f(orders: IOrder[]): IElement[] {
        const result = orders.reduce((accumulator, currentValue) => {
            const date = currentValue.date.split(' ')[0];
    
            if (!accumulator[date]) {
                accumulator[date] = {
                    date,
                    documents: {},
                }
            }
    
            if (!accumulator[date].documents[currentValue.docTypesName]) {
                accumulator[date].documents[currentValue.docTypesName] = {
                    date: currentValue.date,
                    docId: currentValue.docId,
                    docTypesName: currentValue.docTypesName,
                    products: [],
                }
            }
    
            accumulator[date].documents[currentValue.docTypesName].products.push({
                name: currentValue.name,
                price: currentValue.price,
                image: currentValue.image,
                quantity: currentValue.quantity,
            })
    
            return accumulator;
        }, {} as IResultMap)
    
        console.log('result', result);
    
        return Object.values(result).map(currentValue => {
            console.log('currentValue', currentValue);
    
            return {
                ...currentValue,
                documents: Object.values(currentValue.documents)
            }
        });
    }
    
    console.log(f(orders));
    Ответ написан
    Комментировать
  • Как лучше всего распарсить нетипизированный JSON?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Не очень понятен вопрос, но если проблема в типизпции json то в гугле полно json to ts генераторов, которые нaгенерят тебе нужные интерфейсы. Также есть библиотеки, которые позволят тебе этот вопрос автоматизировать и рантайм-хэлперы. И, наконец, если сервер предоставляет свою спеку в open api(swagger), есть генераторы, которые сгенеруруют тебе сразу весь нужный обвес в т.ч. для angular.
    Ответ написан
    Комментировать
  • NextJS: Как импортировать JS-библиотеки?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    import './my-library.js'; // без from

    Если без allowJs, то ещё докинуть файлик my-library.d.ts с деклакрициями:
    declare let var1: number;
    declare function fn1(): void;
    // ...
    Ответ написан
  • Как в TypeScript описать массив массивов с объектами внутри?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Array<Array<Record<string, string>>>
    Ответ написан
    Комментировать
  • Как убрать предупреждение TypeScript?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Хз, что за fastify но если он поддерживает и js и ts - может оставить заботу о типах на того, кто захочет использовать ваш плагин(хоть это и моветон).
    Если он использует только ts, то используя его, вы, очевидно, должны знать ts. В такому случае сделайте именно то, что вам пишет консоль: сделайте соответствующий файл декларации.
    Ответ написан
  • Из-за чего появляется ошибка по 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 Куратор тега TypeScript
    Тлен
    В typescript нельзя изменять существующий класс. Класс - законченная сущность. Конец.

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

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

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Ну, тебе прямым текстом сказано: 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); 
    }
    Ответ написан
    Комментировать