简体   繁体   English

节点模块打字稿类实例类型检查

[英]Node Module Typescript Class instance Type Checking

Currently I am tasked with creating node modules from our Vanilla JS and moving them to typescript. 目前,我的任务是从Vanilla JS创建节点模块并将其移至打字稿。 I rewrote them as classes, added some functionality, wrote a legacy wrapper and the corresponding web pack configuration. 我将它们重写为类,添加了一些功能,编写了旧式包装和相应的Web Pack配置。 The problem is that some of these modules are singletons, so instead of exporting the class by default we want to export an class instance as default. 问题是这些模块中的某些模块是单例的,因此,我们不是要默认导出类,而是要默认导出类实例。 The problem is that I don't get the type checking to work properly: 问题是我没有使类型检查正常工作:

import DebugJs from 'debug';
const test = (test: DebugJs) => {
    test.console('warn', 'does', 'respond', 'with a warning', test);
};

The problem here is that DebugJs is not recognized as a type. 这里的问题是DebugJs无法识别为类型。 So currently I have to import an additional Interface in order to set the type properly. 因此,目前我必须导入其他接口才能正确设置类型。

Just for comparsion, this is what I currently do instead: 只是为了比较,这是我目前所做的:

import DebugJs, { DebugJsInterface } from 'debug';
const test = (test: DebugJsInterface) => {
    test.console('warn', 'does', 'respond', 'with a warning', test);
};

I tried around with namespaces and module declaration, but to be honest, as someone who is totally new to node module creation and quite new to typescript I don't really know what I am doing there. 我尝试了命名空间和模块声明,但是老实说,作为一个对节点模块创建完全陌生并且对打字稿非常陌生的人,我真的不知道我在做什么。

Here is my current index.d.ts file setup 这是我当前的index.d.ts文件设置

import DebugJs from './src/debugJsModule';
import {DebugLevels} from "./src/types/types";

export interface DebugJsInterface {
    levels:DebugLevels;
    enabled:boolean;
    level:number;
    console(...arguments: any): void;
    enableDebug(): void;
    disableDebug(): void;
    setLevel(level:number): void;
}

export interface Module {
    DebugJs: DebugJsInterface;
}

export default DebugJs;
declare module 'debug';

Here the DebugJsInterface is defined as a work around. 在这里,DebugJsInterface被定义为解决方法。 I am also a little puzzled since I thought that the idnex.d.ts should only have type information. 我还感到有些困惑,因为我认为idnex.d.ts应该只包含类型信息。 But if I don't export the class instance from here my module import won't be recognized as a class properly. 但是,如果我不从此处导出类实例,则模块导入不会被正确识别为类。

This is my debugJsModule wrapper which returns a class instance: 这是我的debugJsModule包装器,它返回一个类实例:

import DebugJs from './class/DebugJs';
import { DebugLevels } from 'debug/src/types/types';

const DebugJsInstance: DebugJs = new DebugJs();

export default DebugJsInstance;

The class itself is simply defined as a class and exported as a default export as well 该类本身被简单地定义为一个类,并作为默认导出导出

 class DebugJs { ... } 

Just to be clear, functionality wise everything works, all I want to figure out how I can have the proper type of my importet class instance by using the same import name, in this case DebugJs, without having to rely on an extra importet interface as a workaround. 明确地说,从功能上讲一切正常,所有我想弄清楚如何通过使用相同的导入名称(在本例中为DebugJs)来拥有合适的importet类实例类型,而不必依赖于额外的importet接口,解决方法。

I don't now if this kind of patterns may suite you, but I usually do this by placing the class and the singleton in the same file, and exporting the singleton as default and the class as a named export: 我现在不知道这种模式是否适合您,但是我通常通过将类和单例放置在同一文件中,并将单例导出为默认值并将类导出为命名导出来实现:

class DebugJs {
  // code
}

const debug = new DebugJs();

export default debug;
export {DebugJs};

Then in a client if I import the singleton: 然后在客户端中,如果我导入单例:

import debug from '.../path';

debug.format().log().whatever(); // typings and intellisense works fine. debug will be recognised as DebugJs instance.

And, in the event you need a fresh instance of DebugJs unrelated to the singleton, you can: 而且,如果您需要与单例无关的DebugJs的新实例, DebugJs可以:

import {DebugJs} from '.../path';

const debug = new DebugJs(); // typing and intellisense will work

I'm pretty sure this will work because I use this pattern a lot. 我非常确定这会起作用,因为我经常使用此模式。

However I don't know properly why your setup is not working. 但是我不正确地知道为什么您的设置不起作用。 I don't know if using default exports for types, or maybe combining that with the singleton re-export may be causing your issue. 我不知道是否对类型使用默认导出,或者将其与单例重新导出结合使用可能会导致您的问题。

This snippet doesn't really make that much sense: 这个代码片段实际上没有什么意义:

import DebugJs from 'debug';
const test = (test: DebugJs) => {
    test.console('warn', 'does', 'respond', 'with a warning', test);
};

Here you are not asking for an instanceof DebugJs , you are actually telling typescript to expect an instance of an instance of DebugJs . 在这里,您不是在请求DebugJs的实例,而是在告诉打字稿期望an instance of an instance of DebugJs

Thing is, I don't think it makes any sense here. 问题是,我认为这里没有任何意义。 Why import a instance of something and then immediately not use it? 为什么要导入某事物的实例然后立即不使用它?

Anyway, it is possible, it just requires this syntax: 无论如何,有可能,它只需要以下语法:

const test = (test: typeof DebugJs) => {
    test.console('warn', 'does', 'respond', 'with a warning', test);
};

You'll probably either want to : 您可能会想要:

  1. Not import the instance, but only import DebugJsInterface instead. 不导入实例,而是导入DebugJsInterface That's what you should use for the type guard. 那就是您应该用于类型防护的内容。
  2. Or: don't require it as an argument. 或者:不需要将其作为参数。

Example 1: 范例1:

const test = (test: DebugJsInterface) => {
    test.console('warn', 'does', 'respond', 'with a warning', test);
};

Example 2: 范例2:

const test = () => {
    DebugJs.console('warn', 'does', 'respond', 'with a warning', test);
};

I suspect you want one of the above 我怀疑你想要以上之一

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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