Typescript - Extending existing module declarations
I am still learning typescript, so I got stuck. Also couldnt find anything online.
I am using meteor js which has the following module declaration meteor.d.ts
:
declare module 'meteor/meteor' {
type global_Error = Error;
module Meteor {
/** User **/
interface UserEmail {
address: string;
verified: boolean;
}
interface User {
_id: string;
username?: string | undefined;
emails?: UserEmail[] | undefined;
createdAt?: Date | undefined;
profile?: any;
services?: any;
}
function user(options?: { fields?: Mongo.FieldSpecifier | undefined }): User | null;
function userId(): string | null;
var users: Mongo.Collection<User>;
/** User **/
}
}
Now I have some additional Fields for a user, so I would like to extend the interface User in the module Meteor with some fields:
interface UserAdditonal {
field1: string
field2: string
field3: string
}
How would I do that? I tried this:
declare module "meteor/meteor" {
module Meteor {
function user(options?: {
fields?: Mongo.FieldSpecifier | undefined
}): (User & userAdditonal) | null
var users: Mongo.Collection<User & userAdditonal>
}
}
Which throws an error meteor.d.ts(56, 13): 'users' was also declared here.
and also only works in the same file. Also it is more like overwriting, and less like extending
Is it possible to do globally, so I declare it in one file and all other files that import 'meteor/meteor' get the extended types without importing my file?
Any help is greatly appreciated!
Solution 1:
Yes it is common to enrich your Meteor.users collection (although it is advised not to put too much data in it), and you can definitely tell TypeScript which extra keys you have added.
The idea is simply to enrich the Meteor.User
interface. Because that interface is then used as the return type for Meteor.user()
function and the document type for Meteor.users
collection (as shown in the extract of the definition in your question), it will automatically be available whenever you use them.
// In a file that is imported somewhere
declare module "meteor/meteor" {
module Meteor {
interface User {
field1: string
field2: string
field3: string
}
// If you already have an existing interface that you want to "merge"
// into Meteor.User:
interface User extends UserAdditonal {}
}
}
Then do not forget to import the "meteor/meteor" module, and your extra fields should automatically be available:
import { Meteor } from "meteor/meteor";
Meteor.user().field1; // string
Meteor.users.findOne().field2; // string