简体   繁体   中英

How to support several versions of the same module with typescript?

I'm making a typescript npm package.
It uses discord.js , but there's two main version of discord.js:
* discord.js 11.5
* discord.js v12.0.0-dev

I'd like my module to support both version. I mean, users can install the version of discord.js they want and the package will use the good code.

For another project, in javascript (without typescript), I use this:

const { version } = require("discord.js");
if(version === "12.0.0-dev"){
    // code for v12
} else {
    // code for v11
}

and it works perfectly. But, with typescript, it's more complicated, due to typings. Indeed, discord.js typings aren't the same in v11 and in v12, so I can't compile the code with both versions:

const { Guild, version } = require("discord.js");
if(version === "12.0.0-dev"){
    Guild.iconURL(); // for v12
} else {
    Guild.iconURL; // for v11
}

if the v12 is installed, it will throw iconURL() doesn't exist on Guild and if it's v11, iconURL doesn't exist on Guild .
Is there any way to support both versions in the same package, without creating a branch for each version?

Although not ideal, you could manually download the typings for v11 and v12 and change the module name to something like this:

// discord.js@11.d.ts
declare module 'discord.js@11' {
  ...
}

// discord.js@12.d.ts
declare module 'discord.js@12' {
  ...
}

Then you can import the types like this:

import { Guild as Guild12, version } from "discord.js";
import { Guild as Guild11 } from "discord.js@11";

declare const guild: Guild11 | Guild12 // obviously wouldn't be declared like this in your actual code

// At the time of writing v12.0.2 has been released
if (version === "12.0.2") {
    (guild as Guild12).iconURL(); // for v12
} else {
    (guild as Guild11).iconURL; // for v11
}

You can also define a type guard:

function isV12(guild: Guild11 | Guild12): guild is Guild 12 {
  return version === "12.0.2";
}

if (isV12(guild)) {
  guild.iconURL();
} else {
  guild.iconURL();
}

I tried aliasing discord@11 and discord@12 like this in package.json :

"devDependencies": {
  "discord.js11": "npm:discord.js@11.6.2",
  "discord.js12": "npm:discord.js@12.0.2"
}

but I got this error:

import { Guild as Guild12, version } from "discord.js12";
//                                        ~~~~~~~~~~~~~~
// with pnpm:
// File '/path/to/project/node_modules/.pnpm/registry.npmjs.org/discord.js/12.0.2/node_modules/discord.js/typings/index.d.ts' is not a module. (ts2306)
// with npm:
// File '/path/to/project/node_modules/discord.js12/typings/index.d.ts' is not a module. (ts2306)

npm i formik-v2@npm:formik@2.0.0

or

yarn add formik-v2@npm:formik@2.0.0

then you can

import * from 'formik-v2'

https://medium.com/weekly-webtips/how-to-install-multiple-versions-of-the-same-package-in-npm-71c29b12e253

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