How to handle UnwrapRefSimple in Vue composition api with TypeScript
When using reactive objects Vue composition api I get Typescript errors about UnwrapRefSimple<T>
.
This seems specifically the case when using arrays inside ref()
.
An example.
interface Group<T> {
name: string
items: T[]
}
export function useSomething<T extends object>({ model }: { model: T }) {
const groupsArray = ref([] as Group<T>[])
const group = {
name: 'someGroup',
items: [model],
}
groupsArray.value.push(group) // <-- this line is the problem
return {
groups: groupsArray,
}
}
The error I get is:
Argument of type '{ name: string; items: T[]; }' is not assignable to parameter of type '{ name: string; items: UnwrapRefSimple<T>[]; }'.
Types of property 'items' are incompatible.
Type 'T[]' is not assignable to type 'UnwrapRefSimple<T>[]'.
Type 'T' is not assignable to type 'UnwrapRefSimple<T>'.
Type 'object' is not assignable to type 'UnwrapRefSimple<T>'
I've tried things like adding UnwrapRef
to the code:
import { UnwrapRefSimple } from "@vue/composition-api"
...
items: UnwrapRefSimple<T[]>
But then problems pop up elsewhere in the code and besides, this becomes difficule to read.
Does anyone know how to handle this nicely?
do you know?
how many words do you know
See also questions close to this topic
-
How can I get toast-ui editor content?
I am a student studying. I think I'm doing it conceptually wrong.
I'm trying to use vue3 and type script And I'm going to use toast-ui editor.
I get some errors.
- refEditor.value.invoke is not a function
How can I get toast-ui editor content?
this is my code
<template> <div class="markup-tables flex"> <va-card :title="$t('tables.stripedHoverable')"> <va-card-content> <div id="refEditor" ref="refEditor"></div> <br /> <div class="row justify--end paginationButtons-left"> <va-button class="mr-2 mb-2">List</va-button> </div> <div class="row justify--end paginationButtons-right"> <va-button class="mr-2 mb-2" @click="getHTML">Save</va-button> </div> </va-card-content> </va-card> </div> </template> <script lang="ts"> import '@toast-ui/editor/dist/toastui-editor.css' import Editor from '@toast-ui/editor' import { defineComponent, onMounted, ref } from 'vue' import data from '@/data/tables/markup-table/data.json' export default defineComponent({ name: 'BoardWrite', setup() { const refEditor = ref(null) const getHTML = () => { console.log('getHTML test') let html = refEditor.value.invoke('getHtml') console.log(html) // ERROR } onMounted(() => { const editor = new Editor({ el: refEditor.value, height: '700px', initialEditType: 'markdown', previewStyle: 'vertical', }) editor.getMarkdown() }) return { getHTML, refEditor, } }, }) </script>
-
Custom utility types (generic types) for classes `IsClass` of TypeScript
I am trying to create a
generic type
to make sure the first parameter to be a class. However, the factory function parameter cannot be replaced by ageneric type
.The following upper parts were my attempts. The last part were a working example that directly write the
extends ...
which worked.Why does it works inside a function, but not works as a
generic type
IsClass
?class A { constructor() { } } class B {} class C extends B {} // ERRORS: type IsClass<T extends new (...args: any) => InstanceType<T>> = T type IsClass2<T> = T extends new (...args: any) => InstanceType<T>? T: never type X = IsClass<A> type Y = IsClass2<A> function someFactoryError<T>(clx: IsClass<T>) { return new clx() } someFactoryError(A) function someFactoryError2<T>(clx: IsClass2<T>) { return new clx() } someFactoryError2(A) // WORKS: function someFactoryWorks<T extends new (...args: any) => InstanceType<T>>(clx: T) { return new clx() } const a0 = someFactoryWorks(A) const b0 = someFactoryWorks(B)
Related:
-
Async function passed as prop into React component causing @typescript-eslint/no-misused-promises error
I have the following asynchronous submitNewPatient function which is throwing @typescript-eslint/no-misused-promises error message from elint. Is it possible to adjust the function such that it removes this error?
const submitNewPatient = async (values: PatientFormValues) => { try { const { data: newPatient } = await axios.post<Patient>( `${apiBaseUrl}/patients`, values ); dispatch({ type: "ADD_PATIENT", payload: newPatient }); closeModal(); } catch (e: unknown) { if (axios.isAxiosError(e)) { console.error(e?.response?.data || "Unrecognized axios error"); setError( String(e?.response?.data?.error) || "Unrecognized axios error" ); } else { console.error("Unknown error", e); setError("Unknown error"); } } };
Component used to pass function as a prop:
<AddPatientModal modalOpen={modalOpen} onSubmit={submitNewPatient} error={error} onClose={closeModal} />
I have also tried the following which removes the eslint error message based. However, seems like I am not entering the async code block (perhaps not triggering the async() function):
const submitNewPatient = (values: PatientFormValues) => { async () => { try { const { data: newPatient } = await axios.post<Patient>( `${apiBaseUrl}/patients`, values ); dispatch({ type: "ADD_PATIENT", payload: newPatient }); closeModal(); } catch (e: unknown) { if (axios.isAxiosError(e)) { console.error(e?.response?.data || "Unrecognized axios error"); setError( String(e?.response?.data?.error) || "Unrecognized axios error" ); } else { console.error("Unknown error", e); setError("Unknown error"); } } }; };
-
Deploy VueJS + API app to Azure Static Web App with Gitlab doesn't create functions
I've started creating a small application that will use VueJS as a frontend with Azure Functions as the backend. I was looking at using Azure Static Web Apps to host both components for the application and Gitlab to store / deploy the app.
Everything but the creation of the Azure functions works. Following https://docs.microsoft.com/en-us/azure/static-web-apps/gitlab?tabs=vue
The output from the deploy step, listed below is:
App Directory Location: '/builds/*/valhalla/valhalla-client/dist/spa' was found. Api Directory Location: '/builds/*/valhalla/valhalla-api/dist' was found. Looking for event info Could not get event info. Proceeding Starting to build app with Oryx Azure Static Web Apps utilizes Oryx to build both static applications and Azure Functions. You can find more details on Oryx here: https://github.com/microsoft/Oryx ---Oryx build logs--- Operation performed by Microsoft Oryx, https://github.com/Microsoft/Oryx You can report issues at https://github.com/Microsoft/Oryx/issues Oryx Version: 0.2.20220131.3, Commit: ec344c058843461525ff03b46031553b6e15a47a, ReleaseTagName: 20220131.3 Build Operation ID: |qAffRWArEg8=.deee9498_ Repository Commit : 7cdd5b61f956e6cb8459b13a42af363c4440a97b Detecting platforms... Could not detect any platform in the source directory. Error: Could not detect the language from repo. ---End of Oryx build logs--- Oryx was unable to determine the build steps. Continuing assuming the assets in this folder are already built. If this is an unexpected behavior please contact support. Finished building app with Oryx Starting to build function app with Oryx ---Oryx build logs--- Operation performed by Microsoft Oryx, https://github.com/Microsoft/Oryx You can report issues at https://github.com/Microsoft/Oryx/issues Oryx Version: 0.2.20220131.3, Commit: ec344c058843461525ff03b46031553b6e15a47a, ReleaseTagName: 20220131.3 Build Operation ID: |NGXLP5bVBRk=.705477f6_ Repository Commit : 7cdd5b61f956e6cb8459b13a42af363c4440a97b Detecting platforms... Could not detect any platform in the source directory. Error: Could not detect the language from repo. ---End of Oryx build logs--- Oryx was unable to determine the build steps. Continuing assuming the assets in this folder are already built. If this is an unexpected behavior please contact support. [WARNING] The function language could not be detected. The language will be defaulted to node. Function Runtime Information. OS: linux, Functions Runtime: ~3, node version: 12 Finished building function app with Oryx Zipping Api Artifacts Done Zipping Api Artifacts Zipping App Artifacts Done Zipping App Artifacts Uploading build artifacts. Finished Upload. Polling on deployment. Status: InProgress. Time: 0.1762737(s) Status: InProgress. Time: 15.3950401(s) Status: Succeeded. Time: 30.5043965(s) Deployment Complete :) Visit your site at: https://polite-pebble-0dc00000f.1.azurestaticapps.net Thanks for using Azure Static Web Apps! Exiting Cleaning up project directory and file based variables 00:00 Job succeeded
The deploy step appears to have succeeded, and the frontend is deployed, but there are no Azure Functions showing up in this Static Web App. Is something missed here? So far, the Azure Functions I have are the boiler-plate from instantiating a new Azure Function folder.
image: node:latest variables: API_TOKEN: $DEPLOYMENT_TOKEN APP_PATH: '$CI_PROJECT_DIR/valhalla-client/dist/spa' API_PATH: '$CI_PROJECT_DIR/valhalla-api/dist' stages: - install_api - build_api - install_client - build_client - deploy install_api: stage: install_api script: - cd valhalla-api - npm ci artifacts: paths: - valhalla-api/node_modules/ cache: key: node paths: - valhalla-api/node_modules/ only: - master install_client: stage: install_client script: - cd valhalla-client - npm ci artifacts: paths: - valhalla-client/node_modules/ cache: key: node paths: - valhalla-client/node_modules/ only: - master build_api: stage: build_api dependencies: - install_api script: - cd valhalla-api - npm install -g azure-functions-core-tools@3 --unsafe-perm true - npm run build artifacts: paths: - valhalla-api/dist cache: key: build_api paths: - valhalla-api/dist only: - master needs: - job: install_api artifacts: true optional: true build_client: stage: build_client dependencies: - install_client script: - cd valhalla-client - npm i -g @quasar/cli - quasar build artifacts: paths: - valhalla-client/dist/spa cache: key: build_client paths: - valhalla-client/dist/spa only: - master needs: - job: install_client artifacts: true optional: true deploy: stage: deploy dependencies: - build_api - build_client image: registry.gitlab.com/static-web-apps/azure-static-web-apps-deploy script: - echo "App deployed successfully." only: - master
-
How to global import a stylus file in vite
Now I'm try use
vite
to create avue
app. But have trouble to global import astylus
file invite.config.js
.I try the code from vite docs.
export default defineConfig({ css: { preprocessorOptions: { styl: { additionalData: `@import "./src/assets/styles/common.styl"` } } } })
But it's completely not work.
I got a solution to set global style from github.
export default defineConfig({ css: { preprocessorOptions: { stylus: { globals: { '$highlight-color': 'red' } } } } })
It's works fine, But how to import a styl file globaly? I tried to add 'additionalData' to the workable config. However I got bunch of errors: 'failed to locate file'. It seems like try to import the file in every .vue file, but has trouble to locate the file.
css: { preprocessorOptions: { stylus: { additionalData: `@import "./src/assets/styles/common.styl";`, globals: { '$color-g1': '#F3F4FC', '$color-white': '#FFFFFF', } } } }
Have any idea about this?
-
How can I get type names and member TypeObjects from a ts.TypeObject?
I'm working with a TypeScript compiler to perform some code generation. This is my first time working with the compiler API directly.
With some ugly narrowing below (improvement of which I will save for another question), I'm able to get a
ts.TypeObject
from aFirstStatement
. However, I'm unsure how I can use this object to examine its type.I need to be able to do two things with this type object (or other):
- Extract the top-level type name.
- Recursively extract members' type names down to primitives.
import ts from “typescript”; // get program, checker, and sources const program = ts.createProgram([__filename], {}); const checker = program.getTypeChecker(); const sources = program.getSourceFiles(); // iterate through sources sources.forEach((source)=>{ if(source.fileName === __filename){ // find this file ts.forEachChild(source, (node)=>{ if(ts.SyntaxKind[node.kind] === "FirstStatement"){ // find first statements ts.forEachChild(node, (child)=>{ if(!(child as any).declarations) return; const dec = (child as any).declarations[0]; // get the first declaration if(dec && dec.symbol) console.log(checker.getTypeOfSymbolAtLocation(dec.symbol, node)) }); // get the type of the symbol } }) } });
How can I do this? Or, in the least, where should I be looking in the docs for these kinds of questions?
-
how to make an iterable type in type script that has a key value pair
I am using type script and I want to make a type that represents an object like this the keys generated are genrated dynamically how do I do that
{ dog:true, cat:true, x:true }
currently I am just using any but I woud like a proper type
const matches: any= {}
i get this error when i try to use
{[key: string]: boolean}
Type 'string[] | { [key: string]: boolean; }' must have a '[Symbol.iterator]()' method that returns an iterato
code that causes this error
const docgetter=()=> const matches: { [key: string]: boolean } = {} const documentFieldKeys = Array.isArray(documentNames) ? documentNames : Object.keys(documentNames) return [matches, documentFieldKeys] } const [matches,kycKeys]=docgetter() for(key of kycKeys)
-
function declaration for a generic function return wrapper
How to declare the function
wraps
that takes any function and returns a version of it that differs only in returning an object that wraps the original return type in its propvalue
... and support generics
try it heretype Fn = (...args: any) => any declare function wraps<F extends Fn>( f: F ): (...args: Parameters<F>) => { value: ReturnType<F> } declare function aFunction<T>(t: T): { a: T } const x = aFunction(100) // const x: { a: number } const wf = wraps(aFunction) // const wf: (t: unknown) => { value: { a: unknown } } const y = wf(100) // const y: { value: { a: unknown } } // expected: const y: { value: { a: number } } y.value.a.toExponential() // Property 'toExponential' does not exist on type 'unknown'. ts(2339)
-
Nuxt Compostion API: Change class on hover
<script setup> import Logo from "../assets/svgs/Logo"; import Menu from "../assets/svgs/Menu"; const hover = Boolean let boxTop if (hover === true) { boxTop = 'boxTop--0' } else { boxTop = 'boxTop--20' } </script> <template> <nav class=" w-full fixed flex items-center"> <div class="w-full flex h-full"> <div class="px-6 flex items-center justify-center h-full relative " @mouseover="hover = true" @mouseleave="hover = false" > <Menu class="w-10 fill-white"/> <div class="absolute w-full h-full bg-black" :style="boxTop"></div> </div> </div> </nav> </template>
I want to make it so when the mouse enters the div, the css class "boxTop--0" gets added, and, when the mouse leaves the div, the css class "boxTop--20" gets added. However, I can't figure out how to do it with compositon api.
I would be very greatful for any help.
-
Vue 3 Composition API using getters
I'm refactoring some of my components using the composition API. I'm having problems with one component with asynchronous state trying to get data from one of it's getters.
The original component with the options API:
export default { computed: { ...mapGetters({ incomingChats: "websocket/getIncomingChats", agentId: "token/getAgentId", }), }, methods: { ...mapActions({ addChatSession: "chatSession/addChatSession", }), assigningChatToAgent(chatId) { let agentId = JSON.parse(JSON.stringify(this.agentId)); let assignChatObject = { aggregateId: chatId, agentId: agentId.agentId, }; AssignChatService.assignChatToAgent(assignChatObject); }, }, };
As you can see nothing fancy here. I'm using namespaced vuex modules, passing parameters to a service etc. Now this is the refactored component using the composition api. I'm using the vuex-composition-helper. An important thing to notice is that incomingChats is coming from a websocket message hence is asynchronous. The original component code with the options API works perfect.
setup() { const { incomingChats, agentId } = useGetters({ incomingChats: "websocket/getIncomingChats", agentId: "token/getAgentId", }); const { addChatSession } = useActions({ addChatSession: "chatSession/addChatSession", }); function assigningChatToAgent(chatId) { const agentId = JSON.parse(JSON.stringify(agentId.value)); const assignChatObject = { aggregateId: chatId, agentId: agentId.agentId, }; AssignChatService.assignChatToAgent(assignChatObject); } return { incomingChats, agentId, addChatSession, assigningChatToAgent, }; },
This is the component template:
<template> <ul class="overflow-y-auto pr-2"> <BaseChat v-for="(chat, index) in incomingChats" :key="index" :chat="chat" :class="{ 'mt-0': index === 0, 'mt-4': index > 0 }" @click="assigningChatToAgent(chat.id, chat)" /> </ul> </template>
What is happening with the composition API is that I'm getting this error:
Uncaught ReferenceError: Cannot access 'agentId' before initialization
The error refers to this line here:
const agentId = JSON.parse(JSON.stringify(agentId.value));
That agentId.value is coming from the agentId getter, but I don't understand what I'm doing wrong here. Hope somebody can help.
-
Vue 3: How to get boolean data from parent (using <script setup>) into child?
Firstly, I know this is probably a SUPER easy question, but I've been struggling for an hour and half and I'm kinda done with that. First vue project ever, so I've never had 2 components talk to each other, let alone when
<script setup>
is involved.Any relevant docs that help me understand WHY this works this way would be wonderful. I want to learn how this works, but my google searching is getting me nowhere.
This app is simple, its just toggling light mode and dark mode on some cards. There's more to it than what's below, but I've stripped away the irrelevant (working) code for ease of reading.
My App.vue code:
<script setup> import {ref, defineProps} from "vue"; import card from './components/card.vue' const darkMode = ref(false); const props = defineProps({ darkMode: Boolean }) </script> <template> // Bunch of stuff that is irrelevant to the scope of this problem, it works just fine. </template>
My card.vue code:
<script xmlns="http://www.w3.org/1999/html"> export default { data() { return { } }, } </script> <template> <h1 :class="{ 'text-white': darkMode }"> Content! </h1> </template>
There's more complexity to the project, but all I'm trying to do right now is get them to talk. I just want the class to be added based on whether
darkMode
istrue
orfalse
in the parent.