OK, so for anyone else who’s interested, here’s the solution I’ve come up with. It’s not automagic, but doesn’t require much extra code.
First, the easy bit: allowing the component definition to have a random meteor:
property and define the extra properties added to the Vue component ($subscribe
, etc). Just put this somewhere:
declare module 'vue/types/options' {
interface ComponentOptions<V extends Vue> {
meteor?: any;
}
}
declare module 'vue/types/vue' {
interface Vue {
$subscribe: (name: string, params: any[]) => void;
$autorun: (fn: () => void) => number;
$subReady: Record<string, boolean>;
}
}
Then the tricky bit: allowing data/subscriptions defined within the meteor:
property to be correctly typed. Help came via this StackOverflow answer: https://stackoverflow.com/a/60948413/9614402
Just define this function somewhere:
export const withMeteorData = <TData>(data: TData) => {
return <TMeteorData>() => data as TData & MeteorData;
}
Then, import it into in any Vue component which uses meteor:
, then:
data() {
return withMeteorData({
// normal reactive data goes here
loading: false,
})<{
// stuff defined in meteor: goes here to get added to the component's types
apiKey: string;
}>()
},
meteor: {
$subscribe: {
'users_api_key': () => { return [Meteor.userId()]},
},
apiKey() {
return Meteor.users.findOne(Meteor.userId()!, {fields: {apiKey: 1}})!.apiKey || '';
},
},
If anyone can find a better/automatic solution then please let us know!