Изменить: в сообщении ниже я несколько раз сказал, что я не участвую в модуле. Каждый раз, когда код JavaScript в одном файле вызывается из другого, технически являющегося модулем. Я хотел сказать, что этот модуль автоматически вызывается Quasar во время инициализации скрипта и, как ожидается, будет иметь глобальные побочные эффекты. Модуль никогда не импортируется ни в какой код, который я пишу.
Краткое сообщение:
Я использую Quasar 2.0.0 с поддержкой TypeScript и компонентами класса Vue. Я хочу добавить свойство экземпляра, которое будет доступно в моих классах как: this.$fetch(...);
Я создал загрузочный файл со следующим:
import Vue from "vue";
declare module "vue/types/vue"
{
interface Vue
{
prototype: {
$fetch: (resource: (string | Request), init?: RequestInit) => Promise<Response>
},
$fetch: (resource: (string | Request), init?: RequestInit) => Promise<Response>
}
}
type Context = {
Vue: Vue
};
export default async ({ Vue: vue }:Context) =>
{
vue.prototype.$fetch = async (resource, init) =>
{
return fetch(resource, init);
};
};
Это не вызывает ошибок с TypeScript. Но когда я пытаюсь использовать его в компоненте, я получаю сообщение об ошибке:
<template>
<q-layout>
<q-page-container>
<q-page class="flex flex-center">
<h1>Test</h1>
</q-page>
</q-page-container>
</q-layout>
</template>
<script lang="ts">
import { Vue, Component } from "vue-property-decorator";
@Component
export default class TestPage extends Vue
{
mounted ()
{
this.$fetch("https://www.google.com");
}
}
</script>
Свойство $ fetch не существует для типа TestPage.
Предыдущая (разборка) пост:
Я работаю над приложением Quasar, и для удобства я хотел бы создать модифицированный метод fetch
, который вводит мой ключ API, если запрошенный домен совпадает с моим внутренним доменом. Интерфейс будет примерно таким:
@Component
export default class VueComponent extends Vue
{
mounted()
{
this.$fetch("https://www.example.com/api/endpoint").then(console.log);
}
}
Я знаю, как дать такое определение. Мне просто нужно обновить прототип Vue
согласно https://vuejs.org/v2/cookbook/adding-instance-properties.html:
Vue.prototype.$fetch = async function(request, init)
{
// ... blah ...
};
Согласно документации Quasar, подходящее время для обновление прототипа Vue находится в загрузочном файле. Итак, я создал один:
quasar new boot fetch
Мой загрузочный файл начался довольно просто:
export default async ({ Vue }) =>
{
Vue.prototype.$fetch = async (resource, init) =>
{
return fetch(resource, init);
};
};
Когда все развалилось, я попытался преобразовать в TypeScript. Параметр Vue
неявно имеет тип any
, потому что для объекта параметра не указан тип.
Я пробовал определить тип так:
import Vue from "vue";
type Context = {
Vue: Vue
};
export default async ({ Vue }:Context) =>
Однако это вызвало жалобы на затенение переменных (Vue
определено в верхней области). Я заметил, что переменная Vue
имеет тип VueConstructor<Vue>
, поэтому вместо этого я попробовал:
import { VueConstructor } from "vue";
type Context = {
Vue: VueConstructor
};
export default async ({ Vue }:Context) =>
Это работало для определения функции, но вызывало ошибку в строке Vue.prototype.$fetch = ...
: Небезопасный доступ к члену. $ Fetch для любого значения. TypeScript не ожидает, что Vue.prototype
будет иметь свойство $fetch
. Если бы я делал определение модуля, я бы расширил интерфейс так:
declare module "abc" {
VueConstructor: {
prototype: {
$fetch: ...
}
}
}
Однако я не объявляю модуль - это загрузочный файл. Я попробовал быстро обойти это, определив свой собственный VueConstructor
только в контексте моего загрузочного файла:
interface VueConstructor
{
prototype: {
$fetch: (resource: (string | Request), init?: RequestInit) => Promise<Response>
}
}
type Context = {
Vue: VueConstructor
};
export default async ({ Vue }:Context) =>
{
Vue.prototype.$fetch = async (resource: (string | Request), init?: RequestInit) =>
{
return fetch(resource, init);
};
};
Это наконец заставило TypeScript перестать жаловаться на этот файл, но в тот момент, когда я пытаюсь использовать this.$fetch
в компоненте:
Свойство «$ fetch» не существует для типа «VueComponent».
Поскольку VueComponent
extends Vue
, я думаю, мне нужно обновить определение класса Vue
, но я не понимаю, как это сделать. Я попытался добавить в свой загрузочный файл следующее:
interface Vue
{
$fetch: (resource: (string | Request), init?: RequestInit) => Promise<Response>
}
Но это не сработало. Я не могу просто использовать declare module
, потому что, опять же, я не в модуле. Как расширить тип глобально без модуля?
Vue
(vsVueConstructor
), я не уверен, как обновить интерфейсVue
глобально, чтобы другие скрипты заметили новое свойство, которое я добавил - person stevendesu   schedule 09.10.2020declare module "vue" {}
. Сделайте его модулем, добавивexport {}
на верхнем уровне, если вы не в модуле - person Aluan Haddad   schedule 09.10.2020VueComponent
на самом деле не импортирует vue, он импортирует vue-property-decorator (import { Vue, Component } from "vue-property-decorator";
). Я пробовал использоватьdeclare module "vue-property-decorator"
вместоdeclare module "vue"
, но это дало ошибку, что vue-property-decorator не существует? - person stevendesu   schedule 09.10.2020