声明模块内部的多个接口

时间:2019-11-22 10:59:48

标签: typescript

如果我没弄错,我们为仓库没有界面创建declare module "xyz" {吗?

我正在经历这个code in the repo,作者在声明模块内部创建了多个接口

declare module "express-rate-limit" {
  import { Request, Response, NextFunction } from "express";
  interface RateLimitReturnType {
    (req: Request, res: Response, next: NextFunction): void;
  }
  interface Options {
    max?: number;
    message?: any;
    headers?: boolean;
    windowMs?: number;
    store?: Store | any;
    statusCode?: number;
    skipFailedRequests?: boolean;
    skipSuccessfulRequests?: boolean;
    skip?(req?: Request, res?: Response): boolean;
    onLimitReached?(req?: Request, res?: Response): void;
    handler?(req: Request, res: Response, next?: NextFunction): void;
    keyGenerator?(req: Request, res?: Response): string | Request["ip"];
  }

  interface Store {
    hits: {
      [key: string]: number;
    };
    resetAll(): void;
    resetTime: number;
    setInterval: NodeJS.Timeout;
    resetKey(key: string | any): void;
    decrement(key: string | any): void;
    incr(key: string | any, cb: (err?: Error, hits?: number) => void): void;
  }
  export default function check(options?: Options): RateLimitReturnType;
}

然后这就是他的使用方式

const rateLimiter = RateLimit({
  windowMs: RATE_LIMIT_TIME,
  max: RATE_LIMIT_MAX
});
const publicRateLimiter = RateLimit({
  windowMs: PUBLIC_RATE_LIMIT_TIME,
  max: PUBLIC_RATE_LIMIT_MAX
});
const speedLimiter = slowDown({
  windowMs: SPEED_LIMIT_TIME,
  delayAfter: SPEED_LIMIT_COUNT,
  delayMs: SPEED_LIMIT_DELAY
});

因此,基于此,我有三个问题。

  1. 为什么要在声明模块中创建多个接口?
  2. 打字稿如何知道该类型应与哪个接口匹配?

有人可以向我解释这些内容吗

1。     export default function check(options?: Options): RateLimitReturnType;

  1. interface RateLimitReturnType { (req: Request, res: Response, next: NextFunction): void; }

1 个答案:

答案 0 :(得分:2)

  

为什么要在声明模块中创建多个接口?

因为我们要将它们分组到某个位置。命名空间或模块是执行此操作的理想场所。在大多数情况下,这是自动完成的,因此您不必担心将它们放在一个大文件中。

  

打字稿如何知道类型应该与哪个接口匹配?

创建包时,可以使用prop类型将包中的类型包括在内,例如:

{
  "name": "@drag13/when-do",
  "main": "./dist/index.min.js",
  "types": "./dts/index.d.ts",
  ...
}

这将告诉TypeScript在哪里获取代码的类型。但是TS如何将接口绑定到实际代码?通过命名约定!

这里是示例:

lib.d.ts

interface ICat {
    name: string;
    washed: boolean;
}

export function rename(cat: ICat, name: string): ICat;
export function wish(cat: ICat): ICat;

lib.js

export const rename = (cat, newName) => (cat.name = newName);
export const wash = (cat) => null;

您提到过吗?我在声明中犯了一个错误,第二个函数名为 wish

这就是我们在VsCode中看到的内容:

enter image description here

它认为,有一个函数wish :(。是否会构建?是的,tsc会为您构建它,而不会抱怨,但是稍后会失败。如果编译并检查结果,您会看到类似在这里:

"use strict";
exports.__esModule = true;
var mylib_1 = require("mylib");
var cat = mylib_1.wish({ washed: false, name: 'jHon' });

就我们的模块而言,没有导出愿望功能-它会在运行时失败。

  

导出默认功能检查(选项?:选项):RateLimitReturnType;

这表示,带有代码(js)的实际模块将使用此签名进行默认导出。同样,这只是惯例,在现实生活中,您的代码可能具有另一个默认导出,或者根本没有默认导出。

就像这里:

库d.ts

type Options = {}
type RateLimitReturnType = {};

export default function check(options?: Options): RateLimitReturnType;

库js:

const check = () => 'wrong type';

export default check;

愚弄的代码:

enter image description here

更新:

关于:

  

接口RateLimitReturnType {       (要求:要求,要求:响应,其次:下一步功能):无效;     }

这只是函数的类型声明。 示例:

.d.ts

interface GreetTheCat {
    (catName: string): string;
}

VsCode: enter image description here