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!
