简体   繁体   中英

How to make sure a typescript module conforms to an interface

I'm kind of writing a specific content scraper for some domains. So for those domains supported I just have some functions declared, let's just say there is a

export function getContent(html: string): string {}

So, I have many files with this exact interface for example ...

export interface Domain {
    supportsHttps: boolean;
    getContent(html: string): string;
}

And then for simplicity's sake (to make a map of supported hostname and my domains file), I just

// domainsList.ts
import * as domainA from './domains/domainA';

export default {
    "www.domainA.com": domainA,
}

Then I import my domain list

// index.ts
import * as url from 'url';
import domains from './domainsList';

const maybeDomain: Domain | undefined = domains[url.parse(someUrl).host];

if (maybeDomain) {
    // here I get proper autocompletion ...
    const content = maybeDomain.getContent(someHtml);
} else {
    throw new Error('domain not supported');
}

But if I refactor the name of the function in the interface from getContent to getContents for example, I actually do not have any compilation error from inside all the domains files.

I want to ensure ./domains/domainA.ts exported structure conforms to my Domain interface. Do I have a way to do that ?

Since you are not actually defining the function have the type of Domain the compiler won't link the two of them together, thus no errors.

Also, the Domain interface suits a class much better than a function.

You can get all the checks by defining classes instead of functions. Like this:

class AwesomeDomain implements Domain {
    public supportsHttps: boolean;
    getConten(html: string): string {
        return '';
    }
}

You can find a full example here .

This is my solution, as long as you expose all of your imports exclusively via an index file export.

module/index.ts

import * as A from "./A";
import * as A from "./B";

// type definitions 
export type MyFunc = (args: any[]) => any;
export type MyCollection = {
    [key: string]: MyModule,
}

export interface MyModule {
    KEY: string;

    EXAMPLE_ARRAY: string[];

    someFn: MyFunc;
}

export const COMMANDS = {
    [A.KEY]: A,
    [B.KEY]: B,
} as MyCollection;

module/A.ts

import { MyFunc } from ".";

export const KEY = "some-key";

export const EXAMPLES = [
    "hello",
    "world",
]

export const someFn: CommandFn = async (args: any[]) => {
    return ''
};

If you uncomment one of the exports:

Conversion of type '{ "A": typeof A; "B": typeof B; }' to type 'MyCollection' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
  Property '[A.KEY]' is incompatible with index signature.
    Property 'someFn' is missing in type 'typeof import("...") but required in type 'MyModule'.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM