-
Notifications
You must be signed in to change notification settings - Fork 66
Typescript #25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I'm not really into Typescript, so I haven't particularly thought about it. I'm always happy to accept pull requests, though. (And hey, if I see that this is a thing that would be helpful to many people, I might look into implementing it myself.) |
Typescript type definitions don't only give type definitions for Typescript code, but are used by multiple other tools to provide type information -- such as autocomplete in VSCode. Providing type definitions would therefor help more than just Typescript users. For whoever ends up adding type definitions (which may end up being me, I'm looking into it currently), this reference from Vue is useful: https://vuejs.org/v2/guide/typescript.html#Declaring-Types-of-Vue-Plugins |
@CAD97 Did you find a way to add this to a Ts defined Vue object? I don't understand how I can add this to a file defined as a class, without ussing a decorator (which I don't have, off course) |
I never ended up going much further with this. I never actually ended up using Vue through typescript, and haven't worked with it in over a year. |
I still think that this should be built in for the above reasons, however the workaround for the moment is to dump this into your // This is a very rough interface which says, this object must be functions only
// you could probably do better
interface AsyncComputedObject{
[K : string]:()=>any;
}
// ComponentOptions is declared in types/options.d.ts
declare module "vue/types/options" {
//enable async computed
interface ComponentOptions<V extends Vue> {
asyncComputed?: AsyncComputedObject;
}
} |
Anyone has managed to add it with typescript? |
@recase my comment above you explains how to do it. |
@acronamy I have done what your comment says I have already done. What happens is that I do not know how to use it from a component written with typescript |
I am currently using the typings from this index.d.ts. These provide the interface to import { createDecorator, VueDecorator } from "vue-class-component";
/**
* Create a decorator which turns a property into an asynchronously computed property with vue-async-computed.
*
* @param get a method returning a Promise; the value of the computed property is going to be the resolved value
* @param loading a placeholder to return in the computed property until the promise resolves
* @param lazy whether the promise should be resolved immediately or upon the first request of the computed property
*/
export default function AsyncComputed<T>(get: (() => T | Promise<T>), loading?: T, lazy?: boolean): VueDecorator {
return createDecorator((options, name) => {
(options.asyncComputed || (options.asyncComputed = {}))[name] = {
default: loading,
get,
lazy,
};
});
} With this I can write components such as @Component
export default class C extends Vue {
@AsyncComputed(function(this: C){ return Promise.resolve("Hello World"); })
private value!: string;
} It's not perfect but seems to work for my use cases. It would be nice to get rid of the |
Would this decorator work nicer without using the helper createDecorator the callback seems really odd to me. Still great effort! |
Thanks for having a look at this. I am not sure which callback you are referring to but the
and TypeScript does not complain for me. |
So I think I'm wrong in saying callback. As this function parameter passed through the decorator is what I am referring to, it's just a function that decorates the target. I am use to seeing decorators affecting methods, intercepting the internals of that method and changing the output. I think your right on second glance though. The property is the thing to be decorated and it matters not how. I'm coming from a vanilla TS standpoint / ex Angular fanboy. As for the things that bother you, are there any PRs or plans for type info in decorators I wonder. Personally I've moved away from this library and use vux module class syntax with tsx render functions. Everything seems to just work better for Typescript this way. I think that if your not using vuex for many reasons this is a very useful bit of work you are contributing and please keep it up! |
There had been some discussion at microsoft/TypeScript#4881 but from browsing over this issue it does not seem like there are going to be any changes to this soon. |
Is there any changes you could merge the typings from the forked saraedum/vue-async-computed repo? They seem to be correct. |
I use this ts definitions https://raw.githubusercontent.com/saraedum/vue-async-computed/5debb7dcd81f52183be55e05b866fc43278a9905/types/index.d.ts With this tweak: interface IAsyncComputedProperty<T> {
default?: T | (() => T);
+ get?: AsyncComputedGetter<T>;
- get: AsyncComputedGetter<T>;
watch?: () => void;
shouldUpdate?: () => boolean;
lazy?: boolean;
} Then I took the decorator idea of @saraedum and improved it. import { createDecorator, VueDecorator } from 'vue-class-component';
import { IAsyncComputedProperty } from '..';
export function AsyncComputed<T>(
computedOptions?: IAsyncComputedProperty<T>,
): VueDecorator {
return createDecorator((options, key) => {
options.asyncComputed = options.asyncComputed || {};
const method = options.methods![key];
options.asyncComputed![key] = <IAsyncComputedProperty<T>>{
get: method,
...computedOptions,
};
delete options.methods![key];
});
} Usage: @Component
export default class C extends Vue {
@AsyncComputed()
async helloWorld() {
return "Hello World";
}
} |
Nice. Let me try how your decorator works out here. I think you don't have to patch the type definition if you do something like this: type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
export default function AsyncComputed<T>(computedOptions?: Omit<IAsyncComputedProperty<T>, "get">): VueDecorator {
return createDecorator((options, key) => {
options.asyncComputed = options.asyncComputed || {};
const method = options.methods![key];
options.asyncComputed[key] = {
get: method,
...computedOptions,
} as IAsyncComputedProperty<T>;
delete options.methods![key];
});
} |
@saraedum This looks nice. Thank you. |
Hi @saraedum @TheNoim i have tried your tweak. But it is not working for me 😢 ERROR: Property or method "helloWorld" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. <template>
<p>Test {{ helloWorld }}</p>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import AsyncComputed from '@/plugins/AsyncComputed';
@Component
export default class Test extends Vue {
@AsyncComputed()
public async helloWorld() {
return 'Hello World';
}
}
</script> |
We use this everyday so I am surprised it does not work. Do you have a repo to reproduce this? |
Hi! Thank you very much, everyone. I read comments here and made a simple Vue app for asynchronous computation in Vue + TypeScript. Online demohttps://nwtgck-typescript-vue-async-computed-prac.netlify.com/ How to makeThis is a Git diff for this adaptation. I hope this will be helpful to people reaching this issue :D |
I do want to support this officially, but I'm not all that personally familiar with typescript in this context. I've pushed an experimental If you confirm that these types work (and meet all of your needs), I can merge it into |
I'm not doing anything particularly fancy with prop: {
async get() { return 0; },
default: 'foo'
} But I get the impression that's fairly difficult in Typescript without support for existential types |
Not sure if this is a known limitation, but the new properties created by async-computed aren't known to Typescript. That is, if you do:
you can't refer to
|
I'm trying to use I got a working version in a vanilla environnement 👍 asyncComputed: {
geometry: {
default: { position: [], normal: [] },
get() { // Note it works without async keyword XD !
const loader = new THREE.STLLoader();
return new Promise((resolve, reject) => {
const onLoad = (bufferGeometry) =>
resolve({
position: Array.from(bufferGeometry.attributes.position.array),
normal: Array.from(bufferGeometry.attributes.normal.array),
});
const onProgress = ({ loaded, total }) =>
console.info('progress', ((loaded / total) * 100).toFixed(2) + '%');
const onError = (error) => reject(error);
loader.load(this.stlModelURL, onLoad, onProgress, onError);
});
},
},
}, ... which is then referenced in template as But now, using the <script lang="ts">
// @ts-ignore
import AsyncComputed from 'vue-async-computed'; // TS complains about missing declaration
import { Component, Prop, Vue } from 'vue-property-decorator';
import { BufferGeometry, Vector3 } from 'three';
// @ts-ignore
import { STLLoader } from 'three/examples/jsm/loaders/STLLoader';
Vue.use(AsyncComputed);
...
@AsyncComputed({
default: { position: [], normal: [] },
})
public async geometry() {
const loader = new stlLoader();
return new Promise((resolve, reject) => {
const onLoad = (bufferGeometry: BufferGeometry) =>
resolve({
position: Array.from(bufferGeometry.attributes.position.array) as number[],
normal: Array.from(bufferGeometry.attributes.normal.array) as number[],
});
const onProgress = ({ loaded, total }: { [key: string]: number }) =>
// tslint:disable-next-line:no-console
console.info('progress', ((loaded / total) * 100).toFixed(2) + '%');
const onError = (error: string) => reject(error);
loader.load(this.stlModelURL, onLoad, onProgress, onError);
});
} I get error in console : Did i write correctly the default ? Environnement :
|
@mrozekma the typescript typings won't show up correctly the way you've been using them. You have to use the |
@Sharlaan your code snippet says
Somehow you are not pulling in the typings of async computed. I am not surprised the other line then leads to type errors. Check that you have the correct |
@saraedum i double checked if there were any TS is asking for some line starting with declare module, while the provided index.d.ts doesn't have any. But even adding this missing line not only does not take away the error, but also TS complains about augmentation not possible because the installed Other thing, the error i'm speaking about in my previous post does not seem to point at a typing problem, i'm thinking more about a syntax problem, hence my question : |
@Sharlaan can you share a repository where things don't work as expected so I can see for myself? |
Yes, here AsyncComputed added in last commit. The typings from @foxbenjaminfox are in Note: the working original integration is in |
@Sharlaan I think you really misunderstood what's going on in this thread. Typescript support is not in vue-async-computed yet, you have to pull it in from somewhere else. There was simply no typing in your setup so it could not work. Also it seems you did not see #25 (comment) and the surrounding posts. You did not define the The fixes to make things work (I didn't test, but TypeScript is happy) are here: https://github.com/Sharlaan/webgl-area-picking-vue/pull/1/files |
ah ok thanks, i'm not expert in Vue and TS indeed, i thought copying the index.d.ts linked in this thread would be enough :s EDIT: ok it works ! :) all that were needed is : import VueAsyncComputed, { IAsyncComputedProperty } from 'vue-async-computed';
import { createDecorator, VueDecorator } from 'vue-class-component';
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
function AsyncComputed<T>(computedOptions?: Omit<IAsyncComputedProperty<T>, 'get'>): VueDecorator {
return createDecorator((options, key) => {
options.asyncComputed = options.asyncComputed || {};
const method = options.methods![key];
options.asyncComputed[key] = {
get: method,
...computedOptions,
} as IAsyncComputedProperty<T>;
delete options.methods![key];
});
} |
now with TS v3.5, Omit is built-in ;) |
Hmm, I can't compile Sharlaan's current project, tons of errors about
|
@tioperez Did you ever find a solution to the "Property or method "foo" is not defined on the instance but referenced during render" problem? I've suddenly started getting it as well. |
@mrozekma did you maybe find a solution to this that does not require those workarounds? |
@doits Have you tried the decorator approach described earlier? That mostly works for me in TypeScript. |
As of If any issues are found, or if it's hard to use, please feel free to open other issues on this repository about it. For now I'm going to be closing this one. |
Update: |
Thank you! |
Any plans to add Typescript support?
Thanks.
The text was updated successfully, but these errors were encountered: