node.js - Typescript - kan ikke utvide et modul


Jeg utvikler et personlig prosjekt ved å bruke TypeScript v3.6.4 og Twitter API (twit).

Jeg har også installert @types/twit fra https://www.npmjs.com/package/@types/twit

Jeg vil gjøre en forespørsel til et 'lists/members'-endepunkt.

Koden min er:

import Twit from "twit";

const client = new Twit(...);

client.get('lists/members', {list_id: '123123'})

Men TypeScript gir meg en feil:

src/data/TwitterProvider.ts:16:34 - error TS2769: No overload matches this call.
  Overload 1 of 3, '(path: string, callback: Callback): void', gave the following error.
    Argument of type '{ list_id: string; }' is not assignable to parameter of type 'Callback'.
      Object literal may only specify known properties, and 'list_id' does not exist in type 'Callback'.
  Overload 2 of 3, '(path: string, params?: Params): Promise<PromiseResponse>', gave the following error.
    Argument of type '{ list_id: string; }' is not assignable to parameter of type 'Params'.
      Object literal may only specify known properties, and 'list_id' does not exist in type 'Params'.

     client.get('lists/members', {list_id: 'test'})

Noe som gir mening, siden det ikke finnes noen list_id-egenskap i https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/twit/index.d.ts-filen

Jeg gjorde noe research og opprettet ./src/@types/twit.d.ts:

import "twit";
declare module 'twit' {
  namespace Twit {
    interface Params {
      list_id?: string;
    }
  }
}

Jeg får imidlertid fortsatt den samme feilen.

Min tsconfig.json:

{
  "compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    "moduleResolution": "node",
    "outDir": "dist",
    "rootDir": "src",
    "sourceMap": true
  },
  "typeRoots": [
    "src/@types",
    "node_modules/@types"
  ],
  "include": [
    "src/**/*.ts"
  ],
  "exclude": [
    "node_modules"
  ]
}

Og jeg kjører koden med ts-node src/index.ts

Svar #1

Din modulforsterkningsmetode vil generelt fungere for "standard" npm-pakkedeklarasjoner. Når det gjelder twit-modulen, er dessverre ikke forsterkning av modulen mulig (eller jeg er ikke klar over en riktig måte å gjøre det på).

Twit eksporteres som en CommonJS-modul via export=Twit-syntaks.

Standardeksporterte elementer er ment å fungere som en erstatning for denne oppførselen; imidlertid er de to inkompatible. TypeScript støtter export=for å modellere den tradisjonelle CommonJS- og AMD-arbeidsflyten.

TypeScript tillater tydeligvis bare modulforsterkning av ES-moduler (se eksempel nedenfor), ovennevnte syntaks oppretter eksplisitt en Node CommonJS standardeksport. Denne implementeringen av Node-modulsystemet avviker på noen måter fra den originale CommonJS-standarden, som for eksempel brukes for Babel og TypeScript-kompilatorutdata.

For eksempel lar Node-implementeringen eksportere et enkelt standardobjekt via modules.exports=..., mens CommonJS-spesifikasjonen kun tillater å legge til egenskaper og metoder til exports-objektet som export.foo=... (mer info om ES- og CommonJS-modulimportkonverteringer her og her.

tl;dr: Jeg testet modulforsterkning for Node CommonJS-eksport (utelater navneområder inne i moduler her, da det er et anti-mønster).

lib.d.ts:

declare module "twit3" {
  class Twit3 { bar(): string; }
  export = Twit3;
}

index.ts:

import Twit3 from "twit3";

// Error: Cannot augment module 'twit3' because it resolves to a non-module entity.
declare module "twit3" {
  class Twit3 { baz(): string; }
}

Codesandbox

... fungerte ikke. Å erstatte export =-syntaksen med en navngitt eksport fikk eksemplet til å kompilere (standardeksporter kan generelt ikke utvides).

Hvordan løser man det?

Opprett en sak/PR for twit, hvis det virkelig er et manglende Params-alternativ. I mellomtiden kan en løsning som dette bevare sterke typer for tilleggsegenskaper, samtidig som list_id-alternativet legges til kjøretiden:

const yourOtherParams: Params = {/* insert here */}
client.get("lists/members", { ...yourOtherParams , ...{ list_id: "123123" } });

// or cast directly
client.get("lists/members", { list_id: "123123" } as Params);

Håper det hjelper!

Relaterte artikler