How can I declare type of an ES6 module in Typescript?

I have a generic interface for a repository like this.

export interface IBaseRepository<T> {
    create(model: T): T;
    edit(model: T): T;
    read(): T
}

I’m trying to implement this repository interface in a functional module like this (since it’s basically a stateless singleton).

// user-repository.ts
export function create(model: IUser): IUser { ...code }

export function edit(model: IUser): IUser { ...code }

export function read(): IUser { ...code }

Is there any way to ensure that IBaseRepository is implemented in UserRepository. Or do I have to always implement the repository as a class and export an instantiated singleton?

You can bundle all functions into an object and have that exported.

Something like this:

import { IBaseRepository } from './master';
// user-repository.ts
export function create(model: string): string { return ''; }

export function edit(model: string): string { return ''; }

export function read(): string { return ''; }

export const repository: IBaseRepository<string> = { create, edit, read };

And use it like you would use anything else that module exports:

import { repository } from './repo';

repository.create('test');

Or use the export default to export the functions directly if you want to have that type for the default module export.

import { IBaseRepository } from './master';
// user-repository.ts
export function create(model: string): string { return ''; }

export function edit(model: string): string { return ''; }

export function read(): string { return ''; }

export default { create, edit, read } as IBaseRepository<string>;

And import the module to get it or import the functions separately :

import repo, { create } from './repo';

repo.create('test');

You can still import each function independently of course.

Note use types according to your example I just tried to keep things simpler.

How about this?

interface IFoo {
    foo(): boolean;
    bar();
}

namespace Foo {
    export function foo() {
        return 42;
     }
}

declare type assert<T, K extends T> = {};
declare const check1: assert<IFoo, typeof Foo>;

We get a nice error on the check1:

Type 'typeof Foo' does not satisfy the constraint 'IFoo'.
  Types of property 'foo' are incompatible.
    Type '() => number' is not assignable to type '() => boolean'.
      Type 'number' is not assignable to type 'boolean'.

My example has an inline module, but it should be similar to assert an external module using a import * as Foo from ‘./foo’;