Ответы пользователя по тегу TypeScript
  • TypeScript. Как собрать объект из массива строк?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    На самом деле чтоб была полноценная типизация надо как-то так:
    getStyles<T extends keyof CSSStyleDeclaration>(styles: readonly T[]) {
      return styles.reduce((res, style) => {
        res[style] = this.$nativeElement.style[style];
        return res;
      }, {} as Pick<CSSStyleDeclaration, T>);
    }

    Песочница.

    Разница с решением от Дмитрий в том, что тип получившегося объекта будет содержать только полученные ключи, а не все возможные в CSSStyleDeclaration.
    Ответ написан
    2 комментария
  • Почему Electronjs не видит экспорты после начала работы?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Пальцем в небо: попробуй в tsconfig module: esnext.
    Ответ написан
    Комментировать
  • Как работает конструкция type t = {...}[keyof T]?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Обычное обращение по ключу, как в javascript, что тут непонятного?
    const foo = {
      bar: 1
    };
    foo['bar'] // 1
    const baz = {
      qux: 2
    }['qux']; // 2
    тайпскрит в работе с типами тут ничем не отличается:
    type user = {
        id: number,
        name: string,
    };
    type id = user['id']; // number
    type userKeys = keyof user; // 'id' | 'name'
    type userTypes = user[keyof user]; // number | string
    тип never же просто не учитывается:
    number | string | never - то же самое что number | string.
    Ответ написан
    1 комментарий
  • Definite assignment assertion modifier VS undefined?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    В случае ! ты говришь ts'у: "Я на 100% уверен что undefined тут не будет, можешь не капать мне на мозги.", соответственно все проверки типов происходят как будто значения там есть.

    В случае x | undefined ты просто говоришь, что там может быть и undefined, соответственно во всех местах где ты это используешь, ts потребует от тебя дополнительной проверки на undefined.

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

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Есть такия конструкция: foo as unknown as Type - двойным кастованием вы можете скастовать что угодно во что угодно.
    Только вот делать так не надо, эту убивает весь смысл использования TypeScript.
    Вместо этого вам надо прописать условия в "функции по умолчанию", чтоб она работала так, как это описано, а не хрен пойми как.
    Ответ написан
    6 комментариев
  • Как побороть 431-ю ошибку в nuxt-приложении?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Чтоб передать аргументы командной строки в node можно просто проставить переменную окружения NODE_OPTIONS.

    Но правильное решение - не увеличивать лимиты, а разбираться какого хрена у вас так разжирнел заголовок. Толстый заголовок - мусорный трафик - замедление работы.
    Рекламные сети не должны ничего особо писать в ваши куки и utm-параметры вообще не должны летать внутри вашего сайта.
    Берите дамп запроса(из консоли или с сайта) и смотрите что там за мусор, откуда он взялся и как настроить виновника так, чтоб он этот мусор туда не пихал.
    Ответ написан
    1 комментарий
  • Typescript generic function. How use with other types?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Нет, проблем тут куча.

    T extends [], K extends keyof T - K тут что-то производное от number, потому что ключи(keyof) массива([]) - только цифры.
    let resultSort: T = arr; - бессмысленно, так как arr.sort в любом случае меняет исходный массив.
    a[propertyName].toLowerCase() - упадёт если propertyName будет year, т.к. Number не имеет метода toLowerCase.
    ...

    В итоге функция должна выглядеть как-то так:
    function sortArray<T extends {[key: string]: unknown}, K extends keyof T>  (originArr: T[], propertyName: K, cb: (a: T[]) => T[]): T[] {
      let arr: T[] = JSON.parse(JSON.stringify(originArr));  //deep copy array
    
      arr.sort((a, b) => {
        let nameA = String(a[propertyName]).toLowerCase(),
            nameB = String(b[propertyName]).toLowerCase();
    
        if (nameA < nameB)
          return -1;
        if (nameA > nameB)
          return 1;
        return 0;
      });
    
      return cb(arr);
    }


    Можно не приводить строго к String, но тогда вместо unknown надо указать конкретные типы с которыми предполагается работать, и в самой функции сортировки их учесть.
    Ответ написан
    2 комментария
  • Split getter / mutation / action Vue + Typescript?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Лично у меня подход с классами для vuex не прижился, мне куда удобней разложить логически отдельные наборы функций по отдельным файлам, и потом просто объединить в модуль. Без лишней тонны boilerplate.
    Ответ написан
  • Есть ли смысл делать @Prop типизацию?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Если стоит ts-флаг emitDecoratorMetadata - то vue-property-decorator автоматически проставит type для простого примитивного типа, т.е. конкретно тут вручную можно не указывать. Однако если тип сложный или юнион простых - то это работать уже не будет, и тогда уже надо вручную. (У меня валяется недописанный ts-плагин-трансформер для расширения этого поведения, но руки всё никак не дойдут.)
    Это что касается взаимодействия ts и vue.

    Если вопрос - "нужно ли вообще vue-типизировать свойства", то ответ в целом: на ваш вкус.
    Есть две причины это делать:
    1. Использование вашего компонента вне ts окружения.
    2. Поведение свойства, первый тип которого Boolean, отличается от обычного: такое свойство устанавливается в true если стоит на компоненте, даже если значение отсутствует:
    <component boolean-prop></component>
    // если type: Boolean - booleanProp === true
    // если type иной или отсутствует - booleanProp === undefined
    Ответ написан
    Комментировать
  • Invalid handler for event "click": got undefined?

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

    Твой шаблон превращается компилером примерно в такую render-функцию:
    function anonymous() {
      with (this) {
        return _c('div', [
          _l(
              ([1, 2, 3, 4]),
              function (item) {
                return [
                  _c(
                      'div',
                      {on: {"click": this.toggleMenu}},
                      [_v("\n                   test\n                ")]
                  )
                ]
              }
          )
        ], 2)
      }
    }
    Как видишь, перебор item происходит внутри другой функции, которая задаёт иной контекст(никакой).
    Ответ написан
  • Vue + typescript для чего классы и как их использовать?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Ты не понимаешь что происходит.
    Декоратор @Component превращает класс в Vue-компонент.
    Делая new <name> ты создаёшь не инстанс исходного класса, ты создаёшь инстанс Vue-компонента.
    @Component работает только с классам, коструктор которых не принимает никаких параметров(потому что нет никакой возможности на самом деле их передать).
    Какие параметры принимает конструктор Vue, смотреть надо здесь.

    Условно говоря(на самом деле потроха сложнее), этот код:
    @Template
    @Component
    export default class Item extends Vue {
        @Prop({required: true}) private title!: string;
    
        private get getter() {}
    
        private method() {}
            
        constructor(title: string) {
            super();
        }
    };
    превращается в этот:
    class Item extends Vue {
      constructor() {
        super();
      }
    };
    
    export default Vue.extend({
      template: '<содержимое ./_template.html>',
      props: {
        title: {
          type: String, // только при emitDecoratorMetadata
          required: true
        }
      },
      data: () => new Item(),
      methods: {
        method() {}
      },
      computed: {
        getter() {}
      }
    })

    Для чего? Для того чтоб было красивее, всё было в одном месте и тайпинг с наследованием работал.

    P.S. На всякий случай: декоратор это просто функция, которая работает с переданными параметрами и тем что стоит после него, возвращая результат преобразования. Никакой магии.
    Код:
    @Template
    @Component({})
    export default class Item extends Vue {}
    равносилен:
    export default Template(
      Component({})(
        class Item extends Vue {}
      )
    )
    Ответ написан
    1 комментарий
  • Unresolved variable tooltip for vue + typescript tamplate?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Если это вам пишет PHPStorm - смиритесь. Проверять я это конечно не буду, но скорее всего PHPStorm не знает что делать с vue синтаксисом в html и с @Template, потому что это не официальный и даже не распространённый способ работать с шаблонами Vue.
    Ну или можете накатать feature request в багтрекер шторма.

    Официальны спосб разнести SFC на отдельные файлы(хотя лично мне и отвратительна сама идея этого), это ссылаться на скрит и стили из .vue файла:
    <template>
      <em @click="toggleMenu"
                class="fa far  fa-bars fa-3x opacity-4 transition-all-3 hover-opacity-1 text-pink cursor-pointer nav_menu-toggle-btn"
                v-if="true === isMenuClosed"
      />
    </template>
    <script lang="ts" src="./_script.ts"></script>
    <style lang="sass" src="./_styles.scss"></style>
    Ответ написан
  • Добавить глобальные стили из дочернего компонент?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Какая-то каша на самом деле. =\
    В конечном коде всё должно быть красиво, аккуратно и лаконично, все костыли должны быть спрятаны в либах и в хэлперах.) Если получается не красиво - что-то вы делаете не так.

    Если нужно затипизировать своство конкретного класса, то это можно сделать двумя способами:
    1. просто объявить соответствующее свойство:
    @Template
    @Component
    export default class LayoutDefault extends Vue {
      protected $style: { [key: string]: string };
    
      public constructor(){
        super();
    
        this.$style = { ...this.$style, ... localStyles}
      }
    };
    2. объявить интерфейс с тем же именем и типом экспорта что у класса:
    @Template
    @Component
    export default class LayoutDefault extends Vue {
      public constructor(){
        super();
    
        this.$style = { ...this.$style, ... localStyles}
      }
    };
    export default interface LayoutDefault {
      $style?: { [key: string]: string };
    }

    Если нужно объявить глобально для Vue, то объявляйте глобально для Vue(а не для неведомого "Test", которого нет в модуле 'vue/types/vue'):
    declare module 'vue/types/vue' {
      interface Vue {
        $style: { [key: string]: string }
      }
    }


    P.S. Vue.mixin - это глобальный mixin, т.о. делая так:
    Vue.mixin(
        CSSModules(
            {
                // be careful, 'class' also use by 3-d parties libs classes
                injectAttr: 'class',
                // styles are merged with this.$style by default
                styles:     {...stylesFonts, ...stylesCommon, ...styles},
            }
        )
    );
    вы примешиваете эти стили ко всем Vue-компонентам сразу, независимо от файла.
    Ответ написан
  • JsonLd for vue + typescript?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Если для чего-то нет тайпинга, ты сначала смотришь в @types/<libname> и если там нет - делешь его сам.
    Таковы реалии typescript - ты работаешь преимущественно в javascript окружении.

    Добавь куда-нибудь такое расширение интерфейса:
    declare module 'vue/types/options' {
      interface ComponentOptions<V extends Vue> {
        jsonld?: any; // на самом деле не any, а то чего ждёт либа
      }
    }

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

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Напрямую такой тип задать нельзя. Можно вывести тип, использую функцию-прокладку.
    Ответ написан
    Комментировать
  • TS2322: Type '"about:blank"' is not assignable to type 'Location'.?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Потому что в typescript конкретное свойство должно иметь конкретный тип, и никто не стал заморачиваться со сложной типизацией легаси функциональности. Используйте window.location.href = ....
    Ответ написан
    Комментировать
  • Best way to initialize default values?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Первый случай реактивен, второй и третий - нет. Чтоб понять что и в каком порядке работает - достаточно провести эксперимент. Ну или просеять исходники vue-class-component. Что вам проще.)
    Ответ написан
  • Лучший способ использовать константы Vue + TypeScript?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    А зачем их делать свойствами инстанса? Просто используй в методах.
    Если в "константах" некий текст - можно использовать vue-i18n, чтоб и текст в одном месте и перевод если по-быстрому можно запилить.
    Если не хочется усложнять - всегда можно запихнуть костанты или объект с текстом в Vue.prototype.

    По поводу реактивности - да, будут реактивными, но ты же не будешь их менять.) Чтоб наверняка - просто допиши readonly и typescript тебе не даст их трогать. Если хочется совсем без реактивности, то можно вручную их в хуке created или beforeCreate в this положить.

    По поводу миксинов - для того чтоб их добавлять, тебе не нужны плагины, просто клади в массив
    @Component({
        mixins: [],
    })
    И лишние "getX" методы тебе не нужны, у нас тут не Java.) Миксинить можно и data, защитить от изменений и реактивности можно через Object.freeze().
    Ответ написан
    Комментировать
  • Для чего указывать тип комонента @Component?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    В данном конкретном случае - ничего. Однако данный дженерик используется для выведения типов внутри объекта переданного в @Component.
    @Component({
      methods: {
        getd(){
          alert(this.messages) // Property "mesages" does note exist on type Vue
        }
      }
    })
    export default class Home extends Vue {
      messages: string
    }
    @Component<Home>({
      methods: {
        getd(){
          alert(this.messages) // ok
        }
      }
    })
    export default class Home extends Vue {
      messages: string
    }


    Увы из-за особенностей реализации декораторов, вывести тип неявно в таких случаях не получится.
    Ответ написан
    2 комментария
  • Как создать простейший пакет npm на typescript для проекта на cordova (ionic)?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Суть какбэ в том, что в npm должен быть javascript. От ts там остаются только декларации. Потому сборка.
    Физически ты можешь сбацать чисто ts пакет (где module и\или main указывают на .ts файл), но проблема тут в том, что у каждого своя версия ts, а также настройки ts-транспилятора и линтера свои, из-за чего у рандомного юзера нихрена не соберёся.
    Если ты делаешь чисто для себя, то такой проблемы не будет. Поначалу. А потом зоопарк обязательно разрастётся и ты всё проклянешь.
    Но в целом, прямо сейчас, тебе ничего не мешает просто сообрать ts файлики в папочку, добавить соответствующий package.json и получить нужный пакет без лишних телодвижений.)

    Простейшая же сборка: tsc -d --outDir ./dist и package.json, смотрящий на результат.
    Ответ написан
    2 комментария