Как экспортировать тип вычисляемого свойства в Vue3?

У меня есть компонент Vue3, который выполняет некоторые запросы GraphQL. Он возвращает большой блок JSON, и я вычисляю, чтобы получить из него нужное значение. Я хочу передать это значение дочернему компоненту в качестве реквизита.

Однако в дочернем компоненте мне нужно иметь возможность ввести свой вызов defineProps. Поскольку я хочу принять вычисленное значение, мне нужно, чтобы этот тип отображался здесь. Имеющееся у меня вычисляемое свойство очень велико, поэтому я не хочу вручную вводить его за пределами моего компонента и импортировать в оба. Вместо того, чтобы вводить его вручную, я просто использую оператор typeof.

Как экспортировать этот тип?

// Parent.vue
<script setup lang = "ts">
const { results } = useQuery(...)
const myComputed = computed(() => results.nested.item.is.here)
</script>

<template>
  <Child :passToMe = "myComputed" />
</template>


// Child.vue
const props = defineProps<
  passToMe: ???
>()

Я видел, что вы можете экспортировать компонент с помощью отдельного тега <script>, который будет работать, НО его область действия не позволяет видеть вычисленное свойство из моего <script setup>.

Я мог бы просто использовать тип результатов gql, но, поскольку это значение вложенное, это не совсем работает.

Я не могу переместить запрос на дочерний уровень только для того, чтобы получить там тип, потому что мне нужны другие компоненты для использования компонента <Child>, а этот тип в вычисленном <Parent> является минимально необходимым типом, который я хочу обеспечить.

Итак, как мне экспортировать этот тип для использования в нескольких местах?

Вычисленное значение развернуто, тип passToMe — это любой тип «results.nested.item.is.here».

Estus Flask 21.06.2024 19:00

@EstusFlask абсолютно, но как мне экспортировать тип из родительского в дочерний. Тип представляет собой огромный объект со множеством полей, и я не хочу вводить его вручную. Мне потребовались бы часы, прежде чем я смог бы сделать что-то вроде:export typeof myComputed.value и импортировать это в дочерний элемент.

Jtcruthers 21.06.2024 19:05

Обычно вам нужно ввести его вручную. Это уже дополнительная работа и потенциальная точка отказа для defineProps для обработки импортированных типов, я считаю, что в какой-то момент это было недоступно. Легко ли этого избежать, зависит от особенностей useQuery. Что это, @vue/apollo-composable? Вероятно, вы могли бы извлечь из него тип. Самый простой подход — переместить useMyQuery = () => useQuery(...) в отдельный модуль и использовать ReturnType<typeof useMyQuery>. Поскольку это то, что повторно используется между компонентами, оно в любом случае принадлежит отдельному модулю.

Estus Flask 21.06.2024 19:13

Обычно Vue SFC не экспортирует ничего, кроме самого компонента. Они могут выполнять именованный экспорт, но тот факт, что в некоторых IDE и других инструментах это не удается, доказывает, что это крайний случай.

Estus Flask 21.06.2024 19:14

Это кажется большим упущением, если вы не можете экспортировать типы, используемые в компоненте, когда вам приходится использовать указанный тип в дочернем/родительском компоненте. «поскольку он используется повторно, он в любом случае принадлежит отдельному модулю». Для меня это имеет смысл, но необходимость вводить его вручную, когда он уже существует где-то в коде, кажется упущением.

Jtcruthers 21.06.2024 20:38

Проблема в вашем случае заключается в том, что useQuery() находится в области функции настройки, а экспорт должен быть на верхнем уровне, это не просто проблема с <настройкой сценария>. Возможно, вам не придется вводить его вручную с помощью ReturnType<typeof useMyQuery>. Но сделать это все еще может быть жизнеспособным вариантом. В зависимости от случая это можно считать оптимизацией, поскольку вывод типа в TS может требовать больших ресурсов.

Estus Flask 21.06.2024 21:44
Зод: сила проверки и преобразования данных
Зод: сила проверки и преобразования данных
Сегодня я хочу познакомить вас с библиотекой Zod и раскрыть некоторые ее особенности, например, возможности валидации и трансформации данных, а также...
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Мне нравится библиотека Mantine Component , но заставить ее работать без проблем с Remix бывает непросто.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
TypeScript против JavaScript
TypeScript против JavaScript
TypeScript vs JavaScript - в чем различия и какой из них выбрать?
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Не все нужно хранить на стороне сервера. Иногда все, что вам нужно, это постоянное хранилище на стороне клиента для хранения уникальных для клиента...
Что такое ленивая загрузка в Angular и как ее применять
Что такое ленивая загрузка в Angular и как ее применять
Ленивая загрузка - это техника, используемая в Angular для повышения производительности приложения путем загрузки модулей только тогда, когда они...
0
6
52
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

вы можете получить тип «results.nested.item.is.here» с помощью typeof

const results = {
  nested: { 
    item: {
      is: {
        here: "hello"
      }
    }
  }
}
export type propsType = typeof results.nested.item.is // { here: string }

Затем импортируйте тип propsType в свой компонент Child.

typeof немного особенный, потому что он не делает одно и то же во время выполнения javascript и в объявлениях типов машинописного текста. Следующая строка даст вам тип javascript: либо "string", "object", "number"... Это не то, что вам нужно.

export const runTimeType = typeof results.nested.item.is // "object"

В качестве альтернативы, если у вас есть доступ к типу результатов, вы можете сделать что-то вроде этого:

interface IResult {
  nested : {
    item : {
      is : {
        here: string
      }
    }
  }
}

const results: IResult = {
  nested: { 
    item: {
      is: {
        here: "hello"
      }
    }
  }
}

export type propsType = IResult["nested"]["item"]["is"] // { here: string }

Как правило, я был бы осторожен с использованием typeof, потому что, если typeof useQuery(...) изменится, это также неявно изменит тип реквизита Child, потенциально создавая ошибки, если новый тип несовместим с тем, как Child использует данные.

Спасибо, этого достаточно. Я не осознавал, что можно получить вложенный тип. Поскольку типы useQuery являются внешними по отношению к вычисляемому, а вычисляемый просто получает вложенный тип, мы можем сделать это в отдельном модуле и импортировать его в оба места. Спасибо

Jtcruthers 10.07.2024 19:09

Другие вопросы по теме