如何扩展TypeScript模块而不覆盖它?

wbrvyc0a  于 2023-08-07  发布在  TypeScript
关注(0)|答案(3)|浏览(139)

我想扩展fastify请求对象以包含有关会话的信息。
根据文档,这应该足够了:

declare module "fastify" {
  interface Session {
    user_id: string
    other_key: your_prefer_type
    id?: number
  }
}

字符串
但是,如果我这样做,那么我所有的类型导入都开始失败。

src/factories/createServer.ts:189:19 - error TS2349: This expression is not callable.
  Type 'typeof import("fastify")' has no call signatures.

189   const fastify = Fastify({


如果我做了这样的事

declare module "fastify" {
  import Fastify from 'fastify';

  interface Session {
    user_id: string
    other_key: your_prefer_type
    id?: number
  }

  export = Fastify;
}


然后默认导入工作,但所有其他导入中断,例如。

src/factories/createServer.ts:11:8 - error TS2305: Module '"fastify"' has no exported member 'FastifyRequest'.

11   type FastifyRequest,


我做错什么了?

5kgi1eie

5kgi1eie1#

non-module / global script 声明和经典模块之间有一个不太为人所知的区别:
JavaScript规范声明,任何没有export或顶级await的JavaScript文件都应该被视为脚本而不是模块。
在脚本文件中,变量和类型被声明为在共享全局范围内
在你第一次尝试的时候,很可能会发生的是,你把声明放在了一个带有 no import/export语句的文件中。因此,TS将其视为全局声明,它覆盖了"fastify"模块的默认导出。

// /src/globalDeclaration.d.ts
// NO top-level import/export
// Global declaration type
declare module "fastify" {
  interface Session {
    user_id: string;
    other_key: boolean; // your_prefer_type
    id?: number;
  }
}

// /src/index.ts
import Fastify from "fastify";

const fastify = Fastify(); // Error: Type 'typeof import("fastify")' has no call signatures.ts(2349)

字符串
CodeSandbox上的演示:https://codesandbox.io/s/peaceful-resonance-fc1swm?file=/src/index.ts
要解决此问题,请按照TS文档中的建议:
如果你有一个当前没有任何导入或导出的文件,但你想被视为一个模块,添加行:
export {};
这将改变文件为一个模块导出什么。
因此,让我们添加空导出(可以在文件中的任何位置),以将声明仅转换为模块扩充。
但随后要确保显式导入文件,即使没有任何东西可以从中“导入”:我们只想让TS执行扩充模块的副作用。

// /src/moduleAugmentation.d.ts
export {}; // Make an import or export to turn the file into a module augmentation only

declare module "fastify" {
  interface Session {
    user_id: string;
    other_key: boolean; // your_prefer_type
    id?: number;
  }
}

// /src/index.ts
import Fastify, { FastifyRequest } from "fastify";
import fastifySession from "@fastify/session";
import fastifyCookie from "@fastify/cookie";

import "./moduleAugmentation"; // Now we have to explicitly import the module augmentation file, even just for its side effect

const fastify = Fastify();
fastify.register(fastifyCookie);
fastify.register(fastifySession, {
  secret: "a secret with minimum length of 32 characters"
});

fastify.addHook("preHandler", (request, reply, next) => {
  const b = request.session.other_key;
  //                        ^? (property) Session.other_key: boolean
  next();
});


CodeSandbox上的演示:https://codesandbox.io/s/inspiring-phoebe-ly086x?file=/src/index.ts

xlpyo6sf

xlpyo6sf2#

我的错误是将这些声明添加到了fastify.d.ts文件中。
如果发生这种情况,只需将文件重命名为不是模块的确切名称,例如。my-fastify.d.ts的值。

rbpvctlc

rbpvctlc3#

在自定义材质.d.ts文件中:

import "@mui/material/Typography";

declare module '@mui/material/Typography' {
    interface TypographyPropsVariantOverrides {
        h1Bold: true;
    }
}

字符串
这在实际模块上扩展了TypographyPropsVariantOverrides

相关问题