eslint - Varför antar TypeScript att dokumentobjektet alltid är tillgängligt?
Jag har följande kodrad i en funktion:
if (!document) return;
Av någon anledning får jag följande ESLint-fel från de officiella TypeScript-reglerna:
Onödig villkorlig sats, värdet är alltid falskt. eslint(@typescript-eslint/no-unnecessary-condition)
Det är inte sant att document alltid är sanningsenligt. När koden körs på servern, i ett Node.js-program eller som en del av en React-serverkomponent, är document-objektet inte tillgängligt.
Finns det ett sätt att få TypeScript att förstå att document kan vara undefined?
REDIGERA:
Jag avser att koden ska kunna köras i både en node.js (server) miljö och en webbläsarmiljö. Därför är env i eslint-konfigurationen satt till { node: true, browser: true, } och lib.dom.d.ts inkluderas via denna tsconfig: "lib": ["ESNext", "DOM", "DOM.Iterable"],
Svar #1
Du kan prova dessa två metoder: informera TypeScript om att dokumentet potentiellt kan vara undefined genom att använda en typförsäkran eller en typvakt.
Du kan använda en typförklaring (as) för att tala om för TypeScript att document kan vara undefined: typescript
if (!(document as Document | undefined)) return;
Du kan använda en typvakt för att kontrollera om dokument är definierat:
if (typeof document === 'undefined') return;
Genom att använda en av dessa metoder kommer TypeScript att förstå att dokumentet kan vara undefined, och ESLint-felet bör försvinna.
Svar #2
Den globala document-variabeln deklareras i lib.dom.d.ts som ett Document och inte som ett Document | undefined eller något annat.
Just nu har du två val: inkludera det och acceptera att document är ett Document, eller inte inkludera det och då är document inte känt som en variabel alls. Det finns för närvarande ingen funktion i TypeScript för att "villkorligt" inkludera ett bibliotek, så användningsfallet att ha ett körlängdsätt att upptäcka om DOM existerar stöds inte.
Det finns en öppen funktionsförfrågan på microsoft/TypeScript#53971 som begär bättre stöd för sådan kod som används i flera miljöer, men den har mycket lite engagemang och jag skulle därför inte förvänta mig att se den implementerad inom en snar framtid.
Så just nu är det enda sättet att göra det du frågar om att inte inkludera lib.dom.d.ts, utan istället inkludera eller deklarera din egen version av den där document är av typen Document | undefined (men du måste se till att komma åt den som globalThis.document istället för bara document eftersom att referera till en saknad variabel resulterar i ett ReferenceError och inte undefined (eller om du vill använda document utan att oroa dig, kan du skriva globalThis.document ||= undefined högst upp i din kod, så att document definitivt är en global variabel oavsett vad)).
Detta skulle vara en stor uppgift och det är inte klart att du skulle tjäna mycket på det. Av praktiska skäl skulle jag rekommendera att du bara använder typkonverteringar eller undertrycker den lint-regeln för den raden eller någon annan lösning som inte faktiskt skyddar dig från en eventuellt frånvarande DOM, men åtminstone inte ger dig fel i din miljö.
