remix: Typescript compilation fails
What version of Remix are you using?
1.7.2, Node v16.18.0, npm 8.19.2
Steps to Reproduce
Run npx create-remix@latest, pick Just the basics, any template, Typescript.
Run npx tsc --build inside the app folder.
Expected Behavior
Typescript compiles without errors.
Actual Behavior
Output with Remix App Server, Express, Architect, Fly, Netlify and Vercel templates:
Expand
node_modules/@remix-run/node/dist/upload/fileUploadHandler.d.ts:47:22 - error TS2420: Class 'NodeOnDiskFile' incorrectly implements interface 'File'.
Property 'prototype' is missing in type 'NodeOnDiskFile' but required in type 'File'.
47 export declare class NodeOnDiskFile implements File {
~~~~~~~~~~~~~~
node_modules/typescript/lib/lib.dom.d.ts:2491:5
2491 prototype: Blob;
~~~~~~~~~
'prototype' is declared here.
Found 1 error.
Output with Cloudflare Pages and Workers templates:
Expand
node_modules/typescript/lib/lib.dom.d.ts:25:1 - error TS6200: Definitions of the following identifiers conflict with those in another file: AbortController, AbortSignal, Blob, BodyInit, ByteLengthQueuingStrategy, Cache, CacheStorage, CloseEvent, CountQueuingStrategy, Crypto, CryptoKey, DOMException, Event, EventListener, EventListenerOrEventListenerObject, EventTarget, File, FormData, Headers, HeadersInit, MessageEvent, Navigator, PromiseRejectionEvent, ReadableByteStreamController, ReadableStream, ReadableStreamBYOBReader, ReadableStreamBYOBRequest, ReadableStreamDefaultController, ReadableStreamDefaultReader, ReadableStreamReadResult, Request, Response, StreamPipeOptions, SubtleCrypto, TextDecoder, TextDecoderStream, TextEncoder, TextEncoderStream, TransformStream, start, transform, flush, URL, URLSearchParams, write, abort, close, pull, cancel, WebSocket, WebSocketEventMap, WritableStream, WritableStreamDefaultController, WritableStreamDefaultWriter, caches, console, crypto, navigator, origin, self
25 interface AddEventListenerOptions extends EventListenerOptions {
~~~~~~~~~
node_modules/@cloudflare/workers-types/index.d.ts:4:1
4 declare class AbortController {
~~~~~~~
Conflicts are in this file.
node_modules/typescript/lib/lib.dom.d.ts:666:5 - error TS2687: All declarations of 'kty' must have identical modifiers.
666 kty?: string;
~~~
node_modules/typescript/lib/lib.dom.d.ts:918:5 - error TS2687: All declarations of 'data' must have identical modifiers.
918 data?: T;
~~~~
node_modules/typescript/lib/lib.dom.d.ts:1736:5 - error TS2687: All declarations of 'read' must have identical modifiers.
1736 read?: number;
~~~~
node_modules/typescript/lib/lib.dom.d.ts:1737:5 - error TS2687: All declarations of 'written' must have identical modifiers.
1737 written?: number;
~~~~~~~
node_modules/typescript/lib/lib.dom.d.ts:3653:11 - error TS2430: Interface 'Comment' incorrectly extends interface 'CharacterData'.
Types of property 'after' are incompatible.
Type '(content: Content, options?: ContentOptions | undefined) => Comment' is not assignable to type '(...nodes: (string | Node)[]) => void'.
Types of parameters 'content' and 'nodes' are incompatible.
Type 'string | Node' is not assignable to type 'Content'.
Type 'Node' is not assignable to type 'Content'.
3653 interface Comment extends CharacterData {
~~~~~~~
node_modules/typescript/lib/lib.dom.d.ts:4621:101 - error TS2344: Type 'HTMLElementTagNameMap[K]' does not satisfy the constraint 'Element'.
Type 'HTMLElement | HTMLAnchorElement | HTMLAreaElement | HTMLAudioElement | HTMLBaseElement | ... 57 more ... | HTMLPictureElement' is not assignable to type 'Element'.
Type 'HTMLSelectElement' is not assignable to type 'Element'.
Types of property 'remove' are incompatible.
Type '{ (): void; (index: number): void; }' is not assignable to type '() => Element'.
4621 getElementsByTagName<K extends keyof HTMLElementTagNameMap>(qualifiedName: K): HTMLCollectionOf<HTMLElementTagNameMap[K]>;
~~~~~~~~~~~~~~~~~~~~~~~~
node_modules/typescript/lib/lib.dom.d.ts:4859:11 - error TS2430: Interface 'Element' incorrectly extends interface 'ChildNode'.
Types of property 'after' are incompatible.
Type '(content: Content, options?: ContentOptions | undefined) => Element' is not assignable to type '(...nodes: (string | Node)[]) => void'.
Types of parameters 'content' and 'nodes' are incompatible.
Type 'string | Node' is not assignable to type 'Content'.
4859 interface Element extends Node, ARIAMixin, Animatable, ChildNode, InnerHTML, NonDocumentTypeChildNode, ParentNode, Slottable {
~~~~~~~
node_modules/typescript/lib/lib.dom.d.ts:4859:11 - error TS2430: Interface 'Element' incorrectly extends interface 'ParentNode'.
Types of property 'append' are incompatible.
Type '(content: Content, options?: ContentOptions | undefined) => Element' is not assignable to type '(...nodes: (string | Node)[]) => void'.
Types of parameters 'content' and 'nodes' are incompatible.
Type 'string | Node' is not assignable to type 'Content'.
4859 interface Element extends Node, ARIAMixin, Animatable, ChildNode, InnerHTML, NonDocumentTypeChildNode, ParentNode, Slottable {
~~~~~~~
node_modules/typescript/lib/lib.dom.d.ts:4891:14 - error TS2687: All declarations of 'tagName' must have identical modifiers.
4891 readonly tagName: string;
~~~~~~~
node_modules/typescript/lib/lib.dom.d.ts:4910:101 - error TS2344: Type 'HTMLElementTagNameMap[K]' does not satisfy the constraint 'Element'.
Type 'HTMLElement | HTMLAnchorElement | HTMLAreaElement | HTMLAudioElement | HTMLBaseElement | ... 57 more ... | HTMLPictureElement' is not assignable to type 'Element'.
4910 getElementsByTagName<K extends keyof HTMLElementTagNameMap>(qualifiedName: K): HTMLCollectionOf<HTMLElementTagNameMap[K]>;
~~~~~~~~~~~~~~~~~~~~~~~~
node_modules/typescript/lib/lib.dom.d.ts:7769:11 - error TS2430: Interface 'HTMLSelectElement' incorrectly extends interface 'HTMLElement'.
7769 interface HTMLSelectElement extends HTMLElement {
~~~~~~~~~~~~~~~~~
node_modules/typescript/lib/lib.dom.d.ts:7769:11 - error TS2430: Interface 'HTMLSelectElement' incorrectly extends interface 'HTMLElement'.
The types returned by 'remove()' are incompatible between these types.
Type 'void' is not assignable to type 'Element'.
7769 interface HTMLSelectElement extends HTMLElement {
~~~~~~~~~~~~~~~~~
node_modules/typescript/lib/lib.dom.d.ts:13875:11 - error TS2430: Interface 'Text' incorrectly extends interface 'CharacterData'.
Types of property 'after' are incompatible.
Type '(content: Content, options?: ContentOptions | undefined) => Text' is not assignable to type '(...nodes: (string | Node)[]) => void'.
Types of parameters 'content' and 'nodes' are incompatible.
Type 'string | Node' is not assignable to type 'Content'.
13875 interface Text extends CharacterData, Slottable {
~~~~
node_modules/@types/react/index.d.ts:2854:78 - error TS2344: Type 'HTMLSelectElement' does not satisfy the constraint 'HTMLElement'.
The types returned by 'remove()' are incompatible between these types.
Type 'void' is not assignable to type 'Element'.
2854 select: DetailedHTMLFactory<SelectHTMLAttributes<HTMLSelectElement>, HTMLSelectElement>;
~~~~~~~~~~~~~~~~~
node_modules/@cloudflare/workers-types/index.d.ts:4:1 - error TS6200: Definitions of the following identifiers conflict with those in another file: AbortController, AbortSignal, Blob, BodyInit, ByteLengthQueuingStrategy, Cache, CacheStorage, CloseEvent, CountQueuingStrategy, Crypto, CryptoKey, DOMException, Event, EventListener, EventListenerOrEventListenerObject, EventTarget, File, FormData, Headers, HeadersInit, MessageEvent, Navigator, PromiseRejectionEvent, ReadableByteStreamController, ReadableStream, ReadableStreamBYOBReader, ReadableStreamBYOBRequest, ReadableStreamDefaultController, ReadableStreamDefaultReader, ReadableStreamReadResult, Request, Response, StreamPipeOptions, SubtleCrypto, TextDecoder, TextDecoderStream, TextEncoder, TextEncoderStream, TransformStream, start, transform, flush, URL, URLSearchParams, write, abort, close, pull, cancel, WebSocket, WebSocketEventMap, WritableStream, WritableStreamDefaultController, WritableStreamDefaultWriter, caches, console, crypto, navigator, origin, self
4 declare class AbortController {
~~~~~~~
node_modules/typescript/lib/lib.dom.d.ts:25:1
25 interface AddEventListenerOptions extends EventListenerOptions {
~~~~~~~~~
Conflicts are in this file.
node_modules/@cloudflare/workers-types/index.d.ts:108:12 - error TS2717: Subsequent property declarations must have the same type. Property 'body' must be of type 'ReadableStream<Uint8Array> | null', but here has type 'ReadableStream<any> | null'.
108 readonly body: ReadableStream | null;
~~~~
node_modules/typescript/lib/lib.dom.d.ts:2506:14
2506 readonly body: ReadableStream<Uint8Array> | null;
~~~~
'body' was also declared here.
node_modules/@cloudflare/workers-types/index.d.ts:517:3 - error TS2687: All declarations of 'tagName' must have identical modifiers.
517 tagName: string;
~~~~~~~
node_modules/@cloudflare/workers-types/index.d.ts:518:12 - error TS2717: Subsequent property declarations must have the same type. Property 'attributes' must be of type 'NamedNodeMap', but here has type 'IterableIterator<string[]>'.
518 readonly attributes: IterableIterator<string[]>;
~~~~~~~~~~
node_modules/typescript/lib/lib.dom.d.ts:4860:14
4860 readonly attributes: NamedNodeMap;
~~~~~~~~~~
'attributes' was also declared here.
node_modules/@cloudflare/workers-types/index.d.ts:520:12 - error TS2717: Subsequent property declarations must have the same type. Property 'namespaceURI' must be of type 'string | null', but here has type 'string'.
520 readonly namespaceURI: string;
~~~~~~~~~~~~
node_modules/typescript/lib/lib.dom.d.ts:4874:14
4874 readonly namespaceURI: string | null;
~~~~~~~~~~~~
'namespaceURI' was also declared here.
node_modules/@cloudflare/workers-types/index.d.ts:591:5 - error TS2315: Type 'EventListener' is not generic.
591 > = EventListener<EventType> | EventListenerObject<EventType>;
~~~~~~~~~~~~~~~~~~~~~~~~
node_modules/@cloudflare/workers-types/index.d.ts:599:14 - error TS2315: Type 'EventListenerOrEventListenerObject' is not generic.
599 handler: EventListenerOrEventListenerObject<EventMap[Type]>,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
node_modules/@cloudflare/workers-types/index.d.ts:604:14 - error TS2315: Type 'EventListenerOrEventListenerObject' is not generic.
604 handler: EventListenerOrEventListenerObject<EventMap[Type]>,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
node_modules/@cloudflare/workers-types/index.d.ts:862:3 - error TS2687: All declarations of 'kty' must have identical modifiers.
862 kty: string;
~~~
node_modules/@cloudflare/workers-types/index.d.ts:862:3 - error TS2717: Subsequent property declarations must have the same type. Property 'kty' must be of type 'string | undefined', but here has type 'string'.
862 kty: string;
~~~
node_modules/typescript/lib/lib.dom.d.ts:666:5
666 kty?: string;
~~~
'kty' was also declared here.
node_modules/@cloudflare/workers-types/index.d.ts:1006:3 - error TS2687: All declarations of 'data' must have identical modifiers.
1006 data: ArrayBuffer | string;
~~~~
node_modules/@cloudflare/workers-types/index.d.ts:1006:3 - error TS2717: Subsequent property declarations must have the same type. Property 'data' must be of type 'T | undefined', but here has type 'string | ArrayBuffer'.
1006 data: ArrayBuffer | string;
~~~~
node_modules/typescript/lib/lib.dom.d.ts:918:5
918 data?: T;
~~~~
'data' was also declared here.
node_modules/@cloudflare/workers-types/index.d.ts:1317:3 - error TS2717: Subsequent property declarations must have the same type. Property 'redirect' must be of type 'RequestRedirect | undefined', but here has type 'string | undefined'.
1317 redirect?: string;
~~~~~~~~
node_modules/typescript/lib/lib.dom.d.ts:1552:5
1552 redirect?: RequestRedirect;
~~~~~~~~
'redirect' was also declared here.
node_modules/@cloudflare/workers-types/index.d.ts:1802:3 - error TS2687: All declarations of 'read' must have identical modifiers.
1802 read: number;
~~~~
node_modules/@cloudflare/workers-types/index.d.ts:1802:3 - error TS2717: Subsequent property declarations must have the same type. Property 'read' must be of type 'number | undefined', but here has type 'number'.
1802 read: number;
~~~~
node_modules/typescript/lib/lib.dom.d.ts:1736:5
1736 read?: number;
~~~~
'read' was also declared here.
node_modules/@cloudflare/workers-types/index.d.ts:1803:3 - error TS2687: All declarations of 'written' must have identical modifiers.
1803 written: number;
~~~~~~~
node_modules/@cloudflare/workers-types/index.d.ts:1803:3 - error TS2717: Subsequent property declarations must have the same type. Property 'written' must be of type 'number | undefined', but here has type 'number'.
1803 written: number;
~~~~~~~
node_modules/typescript/lib/lib.dom.d.ts:1737:5
1737 written?: number;
~~~~~~~
'written' was also declared here.
node_modules/@cloudflare/workers-types/index.d.ts:1890:3 - error TS2717: Subsequent property declarations must have the same type. Property 'readableType' must be of type 'undefined', but here has type 'string | undefined'.
1890 readableType?: string;
~~~~~~~~~~~~
node_modules/typescript/lib/lib.dom.d.ts:1770:5
1770 readableType?: undefined;
~~~~~~~~~~~~
'readableType' was also declared here.
node_modules/@cloudflare/workers-types/index.d.ts:1891:3 - error TS2717: Subsequent property declarations must have the same type. Property 'writableType' must be of type 'undefined', but here has type 'string | undefined'.
1891 writableType?: string;
~~~~~~~~~~~~
node_modules/typescript/lib/lib.dom.d.ts:1773:5
1773 writableType?: undefined;
~~~~~~~~~~~~
'writableType' was also declared here.
node_modules/@cloudflare/workers-types/index.d.ts:2001:3 - error TS2717: Subsequent property declarations must have the same type. Property 'type' must be of type 'undefined', but here has type 'string | undefined'.
2001 type?: string;
~~~~
node_modules/typescript/lib/lib.dom.d.ts:1798:5
1798 type?: undefined;
~~~~
'type' was also declared here.
node_modules/@cloudflare/workers-types/index.d.ts:2009:3 - error TS2717: Subsequent property declarations must have the same type. Property 'type' must be of type 'undefined', but here has type 'string | undefined'.
2009 type?: string;
~~~~
node_modules/typescript/lib/lib.dom.d.ts:1806:5
1806 type?: undefined;
~~~~
'type' was also declared here.
node_modules/@cloudflare/workers-types/index.d.ts:2024:33 - error TS2508: No base constructor has the specified number of type arguments.
2024 declare class WebSocket extends EventTarget<WebSocketEventMap> {
~~~~~~~~~~~
node_modules/@cloudflare/workers-types/index.d.ts:2048:50 - error TS2508: No base constructor has the specified number of type arguments.
2048 declare abstract class WorkerGlobalScope extends EventTarget<WorkerGlobalScopeEventMap> {}
~~~~~~~~~~~
node_modules/@cloudflare/workers-types/index.d.ts:2093:12 - error TS2315: Type 'EventListenerOrEventListenerObject' is not generic.
2093 handler: EventListenerOrEventListenerObject<WorkerGlobalScopeEventMap[Type]>,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
node_modules/@cloudflare/workers-types/index.d.ts:2130:12 - error TS2315: Type 'EventListenerOrEventListenerObject' is not generic.
2130 handler: EventListenerOrEventListenerObject<WorkerGlobalScopeEventMap[Type]>,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Found 40 errors.
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Reactions: 31
- Comments: 25 (11 by maintainers)
Commits related to this issue
- Add ci workflow + force node18 Lower tsc version to workaround `https://github.com/remix-run/remix/issues/4371` — committed to i-VRESSE/haddock3-webapp by sverhoeven a year ago
- Downgrade to TypeScript ~4.8 due to remix bug surfacing with TS 4.9 (https://github.com/remix-run/remix/issues/4371) — committed to felixmokross/cashfolio by felixmokross a year ago
Downgrading
typescriptto 4.8 fixes the issue for me. So seems likely to be a bug introduced sometime in 4.9.x.Workaround is to force TS 4.8:
npm install typescript@4.8@lpsinger unfortunately,
prototype = {};is not enough.tscwill then complain thatprototypeis missing properties fromBlob:To recap for any onlookers,
implements Filedoes not requireprototype, so any attempts to patchprototypeare a workaround at best.Looks like TS has included this regression as part of their 5.1.0 milestone, though not sure about the timing of that since 5.1.0 is already out? Maybe 5.1 milestone includes things to fix before 5.2? 🤷
If you don’t want to downgrade Typescript but want to stop the error and get a nudge when this is fixed then put
/* @ts-expect-error */immediately before the line erroring and it will stop complaining. Once it is fixed and stops erroring, it will start complaining again (because there is no error anymore, as expected), just remove the@ts-expect-errorand you have type checking back.You can leave your self a reminder of why too if you like:
Just be careful if you have multiple type checks on the next line as it will stop errors for any of the checks.
Reference: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html#-ts-expect-error-comments
I successfully reproduced the issue with NodeFileOnDisk 👍
However, I’m not sure we will be able to fix errors from Cloudflare pages & workers, as they seem to emanate from the
@cloudflarepackages. Could you fill a report to the relevant repo?Confirming that Typescript 4.9+ is an issue
Steps to Reproduce
Created a fresh remix app. I chose the remix express template Ran the
npm run typecheckand it would fail if I used typescript4.9.5After downgrading to typescript
4.8.4the typecheck command worked:@akomm I think the issue is that we do want to use
implementsbut targeting the TS built-inlib.dom.d.tsdefinition ofFile(andBlob).extendsis semantically different so we’d prefer not to useextends.Talked to @jacob-ebey about this a couple days ago and we didn’t know of a good way to disambiguate the different
Files in theimplementsdeclaration, so the best workaround we came up with was to useextendsand simply have a bunch of unimplemented or pass-through methods/properties. Like I said, not ideal and we’d prefer something that lets us useimplements instead, but couldn’t find any other workarounds or fixes.@pcattori
A small change in the TS Playground example makes the error appear.
I assume the Playground loads node library once it sees any usage of its core modules. You can change “buffer” with “path” or any other core module of node, the effect is the same.
I’m getting this with a
tsc -bon my machine.Running TS 4.9.4 and Remix 1.9.0
@depsimon yes this is terrible as it affects not just libs, but simply all
d.tsfiles, including those of your own project, not just node_modules or the default TS “libs”.