javascript - ES2015-modulsyntaks foretrekkes fremfor tilpassede TypeScript-moduler og navnerom @typescript-eslint/no-namespace


Jeg får følgende feil når jeg kjører npm start:

ES2015-modulsyntaks foretrekkes fremfor tilpassede TypeScript-moduler og -navneområder @typescript-eslint/no-namespace

    namespace InternalThings {...}

Jeg prøvde å undersøke dette, men det er veldig forvirrende.

Hvorfor skjer dette? Hvordan fikser man det?

Jeg prøvde å legge til noen flagg på tsconfig.json-filen min, men så langt ingen suksess;

Svar #1

Dette er en lint-feil, forårsaket av denne lint-regelen: https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/docs/rules/no-namespace.mdx

Hvis du synes regelen er nyttig og vil beholde den, må du endre koden din til å bruke import og export i stedet for namespace. Se dokumentasjonen for regelen for hva som regnes som en fiksering.

Hvis du liker regelen, men vil deaktivere regelen for denne linjen, legg til følgende rett over den:

// eslint-disable-next-line @typescript-eslint/no-namespace

Hvis du ikke liker regelen og vil deaktivere den helt, rediger da .eslintrc-filen din for å ha følgende linje:

rules: {
  "@typescript-eslint/no-namespace": "off"
}

Svar #2

For å fikse denne feilen, i stedet for:

export namespace InternalThings {
    export function myFunction() {
    }

    export class MyClass {
    }
}
import { InternalThings } from './internal-things';

InternalThings.myFunction();

du eksponerer alle medlemmene i navneområdet direkte:

export function myFunction() {
}

export class MyClass {
}

og du importerer det slik:

import * as InternalThings from './internal-things';

InternalThings.myFunction();

Hovedideen er at brukere av modulen din kan importere bare det de vil, eller gi modulen din et annet navn:

import * as CustomModuleName from './internal-things';

CustomModuleName.myFunction();
import { MyClass } from './internal-things';

let field = new MyClass();

Svar #3

Fiks Lint-feil samtidig som du beholder samme API

Hvis du ønsker å håndtere lint-feilen uten å bryte noen nåværende implementasjoner, kan du gjøre følgende, men du bør virkelig se på svaret ovenfor før du forplikter deg til dette: https://stackoverflow.com/a/63574739/349659

Før

Implementation
export namespace Container {
  export function someCall() { }
  export function anotherCall() { }
}
Consumer
import { Container } from './Container'

Container.someCall()
Container.anotherCall()

Etter

Alternativ 1

// These are essentially private
function someCall() { }
function anotherCall() { }

// We expose them here
// This feels like a step towards CommonJS, but is valid ES Module code
export const Container = {
  someCall,
  anotherCall,
}

Alternativ 2

Du kan også definere og kapsle inn funksjonskallene direkte i objektet på denne måten:

export const Container = {
  someCall() {},
  anotherCall() {},
}

Avslutningsvis

Hvis du har en stor kodebase og ønsker å "raskt" tilfredsstille linteren din, kan du gjøre en refaktorering som ovenfor. Sørg for å vurdere dette svaret https://stackoverflow.com/a/63574739/349659 og begrunnelsen bak det.

På slutten av dagen er den raskeste løsningen som ikke krever kodeendring å ganske enkelt slå av denne lint-regelen som nevnt i dette svaret: https://stackoverflow.com/a/58271234/349659

Hvis du begynner fra bunnen av og støter på dette problemet, vil jeg vurdere å bruke den moderne implementeringen som linteren antyder, men du kan oppdage at du liker navnerom og rett og slett ønsker dem også. Hvis du er en del av et team, vil du kanskje først få deres tilbakemelding og følge en teamstandard.


Kanttilfeller og vurderinger

Et tilfelle jeg har støtt på, er å ha flere navneområder i samme fil. I dette scenariet kan du da få navnekollisjoner etter å ha fjernet navneområdet.

Eksempel

Før

export namespace Container {
  export function someCall() { }
  export function anotherCall() { }
}

export namespace AnotherContainer {
  export function someCall() { }
  export function anotherCall() { }
}

Etter

Omkallingskonflikter

I dette scenariet, når du fjerner navneområdet, kan du omdøpe kollisjonene samtidig som du opprettholder eksporten slik:

function containerSomeCall() { }
function containerAnotherCall() { }

export const Container = {
  someCall: containerSomeCall,
  anotherCall: containerAnotherCall,
}

function anotherContainerSomeCall() { }
function anotherContainerAnotherCall() { }

export const AnotherContainer = {
  someCall: anotherContainerSomeCall,
  anotherCall: anotherContainerAnotherCall,
}
Frakobling av koden

Et annet alternativ er å skille dem ut i egne filer. Hvis du likevel ønsker å beholde eksportene fra den opprinnelige filen, må du importere og eksponere dem, noe som kan virke som duplisering, men det kan være et mellomtrinn mot en større refaktorering (senere oppdatere importene til å peke på de nye filene). Dette lar deg også begynne å skrive mer moderne ESM-kode hvis du ønsker, samtidig som du sender nye eksporterte elementer gjennom den gamle modulen.

Container.ts
function someCall() { }
function anotherCall() { }

export const Container = {
  someCall,
  anotherCall,
}
AnotherContainer.ts
function someCall() { }
function anotherCall() { }

export const AnotherContainer = {
  someCall,
  anotherCall,
}
OriginalFile.ts
export * from './Container'
export * from './AnotherContainer'

Vi kan proxy de nye ESM-modulene gjennom den gamle originale modulen.

Relaterte artikler