Giter Site home page Giter Site logo

cloudflare / workers-types Goto Github PK

View Code? Open in Web Editor NEW
360.0 26.0 89.0 267 KB

TypeScript type definitions for authoring Cloudflare Workers.

License: BSD 3-Clause "New" or "Revised" License

TypeScript 100.00%
workers-types cloudflare-workers typescript typescript-definitions

workers-types's Introduction

Cloudflare Workers Types

🛑 This repository was for @cloudflare/workers-types versions ≤ 3 and is no longer maintained.

Since version 4, types are automatically generated from and in the workerd repository.

Find the new README here and the new auto-generation scripts here.

Please raise issues with type definitions in the workerd repository, tagging @cloudflare/workers-types in your report.


Legacy Documentation

Install

npm install -D @cloudflare/workers-types
-- Or
yarn add -D @cloudflare/workers-types

Usage

⚠️ If you're upgrading from version 2, make sure to remove webworker from the lib array in your tsconfig.json. These types are now included in @cloudflare/workers-types.

The following is a minimal tsconfig.json for use alongside this package:

tsconfig.json

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "CommonJS",
    "lib": ["ES2020"],
    "types": ["@cloudflare/workers-types"]
  }
}

Using bindings

It's recommended that you create an ambient type file for any bindings your Worker uses. Create a file named bindings.d.ts in your src directory:

bindings.d.ts

export {};

declare global {
  const MY_ENV_VAR: string;
  const MY_SECRET: string;
  const myKVNamespace: KVNamespace;
}

Auto-Generation

Types are automatically generated from the Workers runtime's source code on every release. However, these generated types don't include any generics or overloads, so to improve ergonomics, some of them are overridden.

The overrides directory contains partial TypeScript declarations. If an override has a different type classification than its generated counterpart – for example, an interface is declared to override a generated class definition – then the override is used instead of the generated output. However, if they're the same type classification (e.g. both the override and the generated output are using class), then their member properties are merged:

  • Members in the override but not in the generated type are included in the output
  • If a member in the override has the same name as one in the generated type, the generated one is removed from the output, and the override is included instead
  • If the member is declared type never in the override, it is removed from the output

If a named type override is declared as a type alias to never, that named type is removed from the output.

JSDoc comments from overrides will also be copied over to the output.

Comment overrides can also be written in Markdown. The docs directory contains these overrides. 2nd level headings are the names of top level declarations (e.g. ## `KVNamespace`), 3rd level headings are for member names (e.g. ### `KVNamespace#put`), and 4th level headings correspond to JSDoc sections for members:

  • #### Parameters: a list with parameters of the form - `param`: param description, these will be formatted as @param tags
  • #### Returns: contents will be copied as-is to the @returns tag
  • #### Examples: fenced code blocks with the language set to js, ts, javascript or typescript will be copied to @example tags

workers-types's People

Contributors

1000hz avatar ashnewmanjones avatar bretthoerner avatar emanh avatar geelen avatar github-actions[bot] avatar gregbrimble avatar ispivey avatar iveelsm avatar jasnell avatar jbampton avatar jdanyow avatar jrf0110 avatar kiannh avatar kobim avatar leo-ar avatar mathew-cf avatar mellowyarker avatar mosch avatar mrbbot avatar penalosa avatar petebacondarwin avatar philipatkinson avatar qwtel avatar robertcepa avatar sbfaulkner avatar sgnatyuk avatar third774 avatar threepointone avatar vlovich avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

workers-types's Issues

Publish new version after 2.1.0

Hey folks! Just a friendly bump if someone has npm publish access. There have been quite a number of changes since the last release. We've just been copy-pasting the source here into our own definition file, so we're not blocked per-say. Thanks 🚀

types for unit testing mocking

Hi,

any chance of integrating audacity's jest+ts unit testing solution to official repo (this or other)? As per udacity/cloudflare-typescript-workers#19 .

Just looked up 70+ repos on github labeled 'cloudflare workers' hoping to find a decent example testing example for jest+ts with Fetch, KV & Rewriter mocking - no success... Wrangler dev will replace onedollarshaveclub's solution for integration testing, but what audacity's solution provides is still something community would love see being covered by cloudlfare team.

Maybe @signalnerve would be keen of filing this gap as he did with auth0 solution https://github.com/signalnerve/workers-auth0-example so elegantly? I'd imagine it'd require some additions to workers-types along with some dedicated example repo with 10-15 tests defined for very basic functionality....

Just an offer, just in case!
Thanks in advance!

Package isn't published?

It doesn't exist in the NPM registry. Did you forget to publish it?

npm ERR! code E404
npm ERR! 404 Not Found - GET https://registry.npmjs.org/@cloudflare%2fworkers-types - Not found
npm ERR! 404 
npm ERR! 404  '@cloudflare/workers-types@^2.0.0' is not in the npm registry.
npm ERR! 404 You should bug the author to publish it (or use the name yourself!)
npm ERR! 404 It was specified as a dependency of 'url-shortener'
npm ERR! 404 
npm ERR! 404 Note that you can also install from a
npm ERR! 404 tarball, folder, http url, or git url.

KV.put `FormData` type?

Can KV store FormData types? It doesn't seem so according to the docs, and how would you even get that data back out with KV.get? There's certainly no documented type there.

Line in question:

value: string | ReadableStream | ArrayBuffer | FormData,

ReferenceError: crypto is not defined

I'm having a problem while running tests using npm test

package.json

{
  "name": "mypackage",
   ...  
  "main": "./lib/index.js",
  "types": "./lib/index.d.ts",
  "directories": {
    "lib": "lib",
    "test": "__tests__"
  },
  "files": [
    "lib"
  ],
  "publishConfig": {
    "access": "public"
  },
  "scripts": {
    "test": "jest",
    "start": "tsc -w --preserveWatchOutput"
  },
  "devDependencies": {
    "@cloudflare/workers-types": "^2.1.0",
    "@testing-library/jest-dom": "^5.11.6",
    "@types/jest": "^26.0.16",
    "jest": "^26.6.3",
    "ts-jest": "^26.4.4",
    "typescript": "^4.1.2"
  }
}

tsconfig.json

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "CommonJS",
    "lib": ["ES2020", "WebWorker"],
    "types": ["@cloudflare/workers-types", "jest"]
  }
}

jest.config.js

module.exports = {
  clearMocks: true,
  coverageDirectory: "coverage",
  coverageProvider: "v8",
  preset: "ts-jest",
  testEnvironment: "jsdom",
};

the code that breaks is the following

token.test.js

import * as token from './token';

describe("Token package", ()=> {
    it("Can generate a token of specific length", ()=>{
        for(var i=0; i< 10; i++) {
            const expectedLength = 1 + Math.floor(Math.random()*64);
            expect(token.generateRandomValue(expectedLength)).toBe(expect.stringMatching(/[a-z0-9]+/));
        }
    })
})

token.ts


export const generateRandomValue = (length:number) => 
    crypto
      .getRandomValues(new Uint16Array(45))
      .reduce(
        (acc, curr, i) =>
          acc +
          ((curr + i) % 3 == 0
            ? curr.toString(36).toUpperCase()
            : curr.toString(36)),
        ""
      )
      .substring(0, length);

I tried also to declare crypto in a setupTest.ts file following https://stackoverflow.com/questions/52612122/how-to-use-jest-to-test-functions-using-crypto-or-window-mscrypto, but jest complains that I'm trying to re-declare crypto.

Any ideas? I tried to play with the configuration but I haven't had any luck. Thank you.

Type conflicts on transpilation when including libs DOM, ESNext, DOM.Iterable, WebWorker

tl;dr: either I'm holding it wrong, or the README instructions to include ["DOM", "DOM.Iterable", "WebWorker"] // As well as "ESNext", etc. as your project requires are wrong. I'm not sure what the answer is, but will poke around a bit.

I was working on a project with a tsconfig like this:

...
    "target": "esnext",
    "module": "esnext",
    "lib": ["ESNext", "WebWorker"]
...

However, I ran in to an error trying to transpile code which accesses the entries() method of a FormData type.

templates/typescript/post_data.ts:48:32 - error TS2339: Property 'entries' does not exist on type 'FormData'.

48     for (let entry of formData.entries()) {
                                  ~~~~~~~

So I read the types and the README, and realized the iterator properties come from DOM.Iterable, so I added that and the DOM lib.

...
    "target": "esnext",
    "module": "esnext",
    "lib": ["DOM", "ESNext", "DOM.Iterable", "WebWorker"]
...

Now, transpilation bonks real hard on conflicts:


> tsc --project ./templates/typescript

node_modules/typescript/lib/lib.dom.d.ts(25,1): error TS6200: Definitions of the following identifiers conflict with those in another file: EventListenerOrEventListenerObject, ImportExportKind, TableKind, ValueType, ExportValue, Exports, ImportValue, ModuleImports, Imports, HeadersInit, BodyInit, RequestInfo, BlobPart, DOMHighResTimeStamp, CanvasImageSource, OffscreenRenderingContext, MessageEventSource, ImageBitmapSource, TimerHandler, PerformanceEntryList, ReadableStreamReadResult, VibratePattern, AlgorithmIdentifier, HashAlgorithmIdentifier, BigInteger, NamedCurve, GLenum, GLboolean, GLbitfield, GLint, GLsizei, GLintptr, GLsizeiptr, GLuint, GLfloat, GLclampf, TexImageSource, Float32List, Int32List, GLint64, GLuint64, Uint32List, BufferSource, DOMTimeStamp, FormDataEntryValue, IDBValidKey, Transferable, BinaryType, CanvasDirection, CanvasFillRule, CanvasLineCap, CanvasLineJoin, CanvasTextAlign, CanvasTextBaseline, ClientTypes, EndingType, IDBCursorDirection, IDBRequestReadyState, IDBTransactionMode, ImageSmoothingQuality, KeyFormat, KeyType, KeyUsage, NotificationDirection, NotificationPermission, OffscreenRenderingContextId, PermissionName, PermissionState, PushEncryptionKeyName, PushPermissionState, ReferrerPolicy, RequestCache, RequestCredentials, RequestDestination, RequestMode, RequestRedirect, ResponseType, ServiceWorkerState, ServiceWorkerUpdateViaCache, VisibilityState, WebGLPowerPreference, WorkerType, XMLHttpRequestResponseType
node_modules/typescript/lib/lib.dom.d.ts(3719,11): error TS2430: Interface 'Comment' incorrectly extends interface 'CharacterData'.
  Types of property 'after' are incompatible.
    Type '(content: string, options?: ContentOptions) => Element' is not assignable to type '(...nodes: (string | Node)[]) => void'.
      Types of parameters 'options' and 'nodes' are incompatible.
        Type 'string | Node' is not assignable to type 'ContentOptions'.
          Type 'string' is not assignable to type 'ContentOptions'.
node_modules/typescript/lib/lib.dom.d.ts(3874,5): error TS2687: All declarations of 'privateKey' must have identical modifiers.
node_modules/typescript/lib/lib.dom.d.ts(3875,5): error TS2687: All declarations of 'publicKey' must have identical modifiers.
node_modules/typescript/lib/lib.dom.d.ts(4961,101): error TS2344: Type 'HTMLElementTagNameMap[K]' does not satisfy the constraint 'Element'.
  Type 'HTMLElement | HTMLCanvasElement | HTMLImageElement | HTMLVideoElement | HTMLAnchorElement | ... 66 more ... | HTMLUListElement' is not assignable to type 'Element'.
    Type 'HTMLSelectElement' is not assignable to type 'Element'.
      The types returned by 'remove()' are incompatible between these types.
        Type 'void' is not assignable to type 'Element'.
node_modules/typescript/lib/lib.dom.d.ts(5251,11): error TS2430: Interface 'Element' incorrectly extends interface 'ChildNode'.
  Types of property 'after' are incompatible.
    Type '(content: string, options?: ContentOptions) => Element' is not assignable to type '(...nodes: (string | Node)[]) => void'.
      Types of parameters 'options' and 'nodes' are incompatible.
        Type 'string | Node' is not assignable to type 'ContentOptions'.
          Type 'string' is not assignable to type 'ContentOptions'.
node_modules/typescript/lib/lib.dom.d.ts(5251,11): error TS2430: Interface 'Element' incorrectly extends interface 'ParentNode'.
  Types of property 'append' are incompatible.
    Type '(content: string, options?: ContentOptions) => Element' is not assignable to type '(...nodes: (string | Node)[]) => void'.
      Types of parameters 'options' and 'nodes' are incompatible.
        Type 'string | Node' is not assignable to type 'ContentOptions'.
          Type 'string' is not assignable to type 'ContentOptions'.
node_modules/typescript/lib/lib.dom.d.ts(5277,14): error TS2687: All declarations of 'namespaceURI' must have identical modifiers.
node_modules/typescript/lib/lib.dom.d.ts(5300,14): error TS2687: All declarations of 'tagName' must have identical modifiers.
node_modules/typescript/lib/lib.dom.d.ts(5331,101): error TS2344: Type 'HTMLElementTagNameMap[K]' does not satisfy the constraint 'Element'.
  Type 'HTMLElement | HTMLCanvasElement | HTMLImageElement | HTMLVideoElement | HTMLAnchorElement | ... 66 more ... | HTMLUListElement' is not assignable to type 'Element'.
    Type 'HTMLSelectElement' is not assignable to type 'Element'.
node_modules/typescript/lib/lib.dom.d.ts(8414,11): error TS2430: Interface 'HTMLSelectElement' incorrectly extends interface 'HTMLElement'.
  Types of property 'remove' are incompatible.
    Type '{ (): void; (index: number): void; }' is not assignable to type '() => Element'.
node_modules/typescript/lib/lib.dom.d.ts(15663,11): error TS2430: Interface 'Text' incorrectly extends interface 'CharacterData'.
  Types of property 'after' are incompatible.
    Type '(content: string, options?: ContentOptions) => Element' is not assignable to type '(...nodes: (string | Node)[]) => void'.
      Types of parameters 'options' and 'nodes' are incompatible.
        Type 'string | Node' is not assignable to type 'ContentOptions'.
          Type 'string' is not assignable to type 'ContentOptions'.
node_modules/typescript/lib/lib.webworker.d.ts(25,1): error TS6200: Definitions of the following identifiers conflict with those in another file: EventListenerOrEventListenerObject, ImportExportKind, TableKind, ValueType, ExportValue, Exports, ImportValue, ModuleImports, Imports, HeadersInit, BodyInit, RequestInfo, BlobPart, DOMHighResTimeStamp, CanvasImageSource, OffscreenRenderingContext, MessageEventSource, ImageBitmapSource, TimerHandler, PerformanceEntryList, ReadableStreamReadResult, VibratePattern, AlgorithmIdentifier, HashAlgorithmIdentifier, BigInteger, NamedCurve, GLenum, GLboolean, GLbitfield, GLint, GLsizei, GLintptr, GLsizeiptr, GLuint, GLfloat, GLclampf, TexImageSource, Float32List, Int32List, GLint64, GLuint64, Uint32List, BufferSource, DOMTimeStamp, FormDataEntryValue, IDBValidKey, Transferable, BinaryType, CanvasDirection, CanvasFillRule, CanvasLineCap, CanvasLineJoin, CanvasTextAlign, CanvasTextBaseline, ClientTypes, EndingType, IDBCursorDirection, IDBRequestReadyState, IDBTransactionMode, ImageSmoothingQuality, KeyFormat, KeyType, KeyUsage, NotificationDirection, NotificationPermission, OffscreenRenderingContextId, PermissionName, PermissionState, PushEncryptionKeyName, PushPermissionState, ReferrerPolicy, RequestCache, RequestCredentials, RequestDestination, RequestMode, RequestRedirect, ResponseType, ServiceWorkerState, ServiceWorkerUpdateViaCache, VisibilityState, WebGLPowerPreference, WorkerType, XMLHttpRequestResponseType
node_modules/typescript/lib/lib.webworker.d.ts(89,5): error TS2687: All declarations of 'privateKey' must have identical modifiers.
node_modules/typescript/lib/lib.webworker.d.ts(90,5): error TS2687: All declarations of 'publicKey' must have identical modifiers.
node_modules/typescript/lib/lib.webworker.d.ts(1180,13): error TS2403: Subsequent variable declarations must have the same type.  Variable 'DOMMatrixReadOnly' must be of type '{ new (init?: string | number[]): DOMMatrixReadOnly; prototype: DOMMatrixReadOnly; fromFloat32Array(array32: Float32Array): DOMMatrixReadOnly; fromFloat64Array(array64: Float64Array): DOMMatrixReadOnly; fromMatrix(other?: DOMMatrixInit): DOMMatrixReadOnly; toString(): string; }', but here has type '{ new (init?: string | number[]): DOMMatrixReadOnly; prototype: DOMMatrixReadOnly; fromFloat32Array(array32: Float32Array): DOMMatrixReadOnly; fromFloat64Array(array64: Float64Array): DOMMatrixReadOnly; fromMatrix(other?: DOMMatrixInit): DOMMatrixReadOnly; }'.
node_modules/typescript/lib/lib.webworker.d.ts(1277,5): error TS2375: Duplicate number index signature.
node_modules/typescript/lib/lib.webworker.d.ts(1574,5): error TS2375: Duplicate number index signature.
node_modules/typescript/lib/lib.webworker.d.ts(1648,13): error TS2403: Subsequent variable declarations must have the same type.  Variable 'FormData' must be of type '{ new (form?: HTMLFormElement): FormData; prototype: FormData; }', but here has type '{ new (): FormData; prototype: FormData; }'.
node_modules/typescript/lib/lib.webworker.d.ts(2214,14): error TS2717: Subsequent property declarations must have the same type.  Property 'canvas' must be of type 'HTMLCanvasElement | OffscreenCanvas', but here has type 'OffscreenCanvas'.
node_modules/typescript/lib/lib.webworker.d.ts(2401,13): error TS2403: Subsequent variable declarations must have the same type.  Variable 'Notification' must be of type '{ new (title: string, options?: NotificationOptions): Notification; prototype: Notification; readonly maxActions: number; readonly permission: NotificationPermission; requestPermission(deprecatedCallback?: NotificationPermissionCallback): Promise<...>; }', but here has type '{ new (title: string, options?: NotificationOptions): Notification; prototype: Notification; readonly maxActions: number; readonly permission: NotificationPermission; }'.
node_modules/typescript/lib/lib.webworker.d.ts(4758,14): error TS2717: Subsequent property declarations must have the same type.  Property 'canvas' must be of type 'HTMLCanvasElement | OffscreenCanvas', but here has type 'OffscreenCanvas'.
node_modules/typescript/lib/lib.webworker.d.ts(5432,11): error TS2320: Interface 'WorkerGlobalScope' cannot simultaneously extend types 'WindowOrWorkerGlobalScope' and 'WorkerUtils'.
  Named property 'atob' of types 'WindowOrWorkerGlobalScope' and 'WorkerUtils' are not identical.
node_modules/typescript/lib/lib.webworker.d.ts(5432,11): error TS2320: Interface 'WorkerGlobalScope' cannot simultaneously extend types 'WindowOrWorkerGlobalScope' and 'WorkerUtils'.
  Named property 'btoa' of types 'WindowOrWorkerGlobalScope' and 'WorkerUtils' are not identical.
node_modules/typescript/lib/lib.webworker.d.ts(5826,13): error TS2403: Subsequent variable declarations must have the same type.  Variable 'onmessage' must be of type '(this: Window, ev: MessageEvent) => any', but here has type '(this: DedicatedWorkerGlobalScope, ev: MessageEvent) => any'.
node_modules/typescript/lib/lib.webworker.d.ts(5836,13): error TS2403: Subsequent variable declarations must have the same type.  Variable 'location' must be of type 'Location', but here has type 'WorkerLocation'.
node_modules/typescript/lib/lib.webworker.d.ts(5837,13): error TS2403: Subsequent variable declarations must have the same type.  Variable 'onerror' must be of type 'OnErrorEventHandlerNonNull', but here has type '(this: DedicatedWorkerGlobalScope, ev: ErrorEvent) => any'.
node_modules/typescript/lib/lib.webworker.d.ts(5839,13): error TS2403: Subsequent variable declarations must have the same type.  Variable 'self' must be of type 'Window & typeof globalThis', but here has type 'WorkerGlobalScope & typeof globalThis'.
node_modules/typescript/lib/lib.webworker.d.ts(5847,13): error TS2403: Subsequent variable declarations must have the same type.  Variable 'navigator' must be of type 'Navigator', but here has type 'WorkerNavigator'.
templates/typescript/cache_ttl.ts(10,7): error TS2769: No overload matches this call.
  Overload 1 of 2, '(input: RequestInfo, init?: RequestInit): Promise<Response>', gave the following error.
    Type '{ cacheTtl: number; cacheEverything: boolean; cacheKey: string; }' is not assignable to type 'CfRequestProperties | CfRequestInit'.
      Object literal may only specify known properties, and 'cacheTtl' does not exist in type 'CfRequestProperties | CfRequestInit'.
  Overload 2 of 2, '(input: RequestInfo, init?: RequestInit): Promise<Response>', gave the following error.
    Type '{ cacheTtl: number; cacheEverything: boolean; cacheKey: string; }' is not assignable to type 'CfRequestProperties | CfRequestInit'.
      Object literal may only specify known properties, and 'cacheTtl' does not exist in type 'CfRequestProperties | CfRequestInit'.
templates/typescript/conditional_response.ts(29,7): error TS2367: This condition will always return 'false' since the types 'string' and 'number' have no overlap.
../workers-types/index.d.ts(183,3): error TS2687: All declarations of 'namespaceURI' must have identical modifiers.
../workers-types/index.d.ts(187,3): error TS2687: All declarations of 'tagName' must have identical modifiers.
../workers-types/index.d.ts(191,12): error TS2717: Subsequent property declarations must have the same type.  Property 'attributes' must be of type 'NamedNodeMap', but here has type 'Iterator<{ name: string; value: string; }, any, undefined>'.

I realize a few of those errors are because I have a mis-shapen cf object, as I've been playing around with type definitions locally. But the others seem real.

List keys via for-await-of

First, I know this is not the right place for this question. But I can't find the official worker runtime. Maybe it is an internal project?

I had an idea for a small extension to the runtime, but I don't know where to ask the question. That's why I have landed here and I thank you for your patience 🙇 .

My desired extension would be to simplify listing of keys, by using "for await...of".

The current API allows for queries by prefix, but only up to a single 'limit' worth of items. Iterating for more items can be a bit awkward:

const value = await NAMESPACE.list({"prefix": "user:1:"})
let list_complete = value.list_complete

while (!list_complete) {
  const cursor = value.cursor

  const next_value = await NAMESPACE.list({"cursor": cursor})
  list_complete = next_value.list_complete
  // use values
}

This can be improved by supporting the "Symbol.asyncIterator" API. With that extension, iterating values could be as easy as:

for await (const value of NAMESPACE.list({"prefix": "user:1:"})) {
  // use values
}

I hope that this proposal may be passed along, or you can point me in the right direction of where to take this feedback. But I also know that this may have been intentionally omitted. So either way, thanks for reading this 👍

Type definition missing for KVNamespace.getWithMetadata()

Thank you for maintaining this package--it makes writing worker code so much easier.

I noticed there is a new method for KVNamespace: getWithMetadata(). It is not in the type definitions, however, so I've had to patch it in myself:

declare global {
  export interface KVNamespace {
    getWithMetadata(key: string): KVValue<{ value: string; metadata: any }>
  }
}

I'm sure that is not quite the best way to type the function. If you could add the proper type definition, I will give my cat an extra treat.

I may attempt to add the proper type definition and submit a PR.

Add possibility to narrow down key space of KVNamespace

Sometimes a KV namespace might be used only for a known subset of strings. It would be great to define it directly in the type of KVNamespace to have typescript checking whether we have only used the keys of this known subset.

Example 1

A developer might want to use a KV namespace to store settings which can be changed through a special route. In this case it would be great to have TypeScript checking whether the used keys are fine. Example:

// Only the keys "enabled" and "color" should be used in the KVNamespace
const settings = KVNamespace<"enabled" | "color">

// fine
settings.get("enabled")

// we would get an error here and thus we see that we have misspelled the key
settings.get("ennabled")

Example 2

Usage of template literal types to define the key space:

const kvNamespace = KVNamespace<`data${number}`>

// fine
kvNamespace.get("data1")

// errors
kvNamespace.get("dataa1")
kvNamespace.get("data-1")

Property 'cf' does not exist on type 'Request'

I tried adding this library to an existing Creact-React-App application.

I've added a hello world function, and I wrote this:

export const onRequest: PagesFunction = async (context) => {
  // Contents of context object
  const {
    request, // same as existing Worker API
    env, // same as existing Worker API
    params, // if filename includes [id] or [[path]]
    waitUntil, // same as ctx.waitUntil in existing Worker API
    next, // used for middleware or to fetch assets
    data, // arbitrary space for passing data between middlewares
  } = context;

  return new Response(
    JSON.stringify({
      country: request.cf.country,
      continent: request.cf.continent,
    })
  );
};

However I am getting error:

Property 'cf' does not exist on type 'Request'.ts(2339)

With //@ts-ignore it works just fine though.

What am I missing here?

Result of WebSocketPair can't be destructured

Steps to reproduce

  • Install "@cloudflare/workers-types": "^3.1.1",
  • write const [client, server] = new WebSocketPair();

Actual result

image

Expected result

Code above to be handled the same by typescript as

const webSocketPair = new WebSocketPair();
const client = webSocketPair[0];
const server = webSocketPair[1];

Cause

This is probably because the type for WebSocketPair is

declare const WebSocketPair: { new(): { 0: WebSocket; 1: WebSocket; }; };

instead of

declare const WebSocketPair: { new(): [WebSocket, WebSocket]; };

Default Worker Object for new modules format

Maybe something like this:

declare interface CFWorker<Environment = Record<string, unknown>> {
  fetch(request: Request, env: Environment): Promise<Response>
}

Which would let a user:

declare type Environment = {
  MYKV: KVNamespace
}

export default {
  async fetch(request, env): Promise<Response> {
    await env.MYKV.put('key', 'value')
    return new Response('Hello, world!')
  },
} as CFWorker<Environment>

Where is WebAssembly type?

In new version of workers-type, I cant find WebAssembly type(which present in "dom", "webworker" libs)

Using with a Workers SSR React app

Hey Cloudflare friends 👋

So I found a bit of a TypeScript problem with SSR React and Cloudflare. Based on workers-types, you shouldn't include the built-in DOM types on a Workers project which makes sense because workers isn't a DOM environment. The problem is that some of the code we're writing runs in the worker and some of it runs in the browser.

So I do need both types available in different parts of my file. Unfortunately AFAIK is not possible with TypeScript. So we need to have both types available for the whole file. Unfortunately, when I include DOM types with @cloudflare/workers-types, I get a bunch of errors because the types aren't compatible.

I'm not sure what to do about this. Have y'all faced this before?

Here's what I get when I try to have both DOM and `@cloudflare/workers-types` at the same time:
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, Cache, CacheStorage, CloseEvent, Crypto, CryptoKey, DOMException, Event, EventListener, EventListenerOrEventListenerObject, EventTarget, File, FormData, Headers, HeadersInit, MessageEvent, PromiseRejectionEvent, ReadableStream, ReadableStreamDefaultReader, Request, Response, StreamPipeOptions, SubtleCrypto, TextDecoder, TextEncoder, TransformStream, URL, URLSearchParams, WebSocket, WebSocketEventMap, WritableStream, WritableStreamDefaultWriter, caches, console, crypto, 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:287:5 - error TS2687: All declarations of 'privateKey' must have identical modifiers.

287     privateKey?: CryptoKey;
        ~~~~~~~~~~

node_modules/typescript/lib/lib.dom.d.ts:288:5 - error TS2687: All declarations of 'publicKey' must have identical modifiers.

288     publicKey?: CryptoKey;
        ~~~~~~~~~

node_modules/typescript/lib/lib.dom.d.ts:650:5 - error TS2687: All declarations of 'kty' must have identical modifiers.

650     kty?: string;
        ~~~

node_modules/typescript/lib/lib.dom.d.ts:877:5 - error TS2687: All declarations of 'data' must have identical modifiers.

877     data?: T;
        ~~~~

node_modules/typescript/lib/lib.dom.d.ts:1701:5 - error TS2687: All declarations of 'read' must have identical modifiers.

1701     read?: number;
         ~~~~

node_modules/typescript/lib/lib.dom.d.ts:1702:5 - error TS2687: All declarations of 'written' must have identical modifiers.

1702     written?: number;
         ~~~~~~~

node_modules/typescript/lib/lib.dom.d.ts:3568: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'.
            Type 'Node' is not assignable to type 'string'.

3568 interface Comment extends CharacterData {
               ~~~~~~~

node_modules/typescript/lib/lib.dom.d.ts:4632:101 - error TS2344: Type 'HTMLElementTagNameMap[K]' does not satisfy the constraint 'Element'.
  Type 'HTMLElement | HTMLAnchorElement | HTMLAreaElement | HTMLAudioElement | HTMLBaseElement | ... 63 more ... | HTMLFrameSetElement' 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'.

4632     getElementsByTagName<K extends keyof HTMLElementTagNameMap>(qualifiedName: K): HTMLCollectionOf<HTMLElementTagNameMap[K]>;
                                                                                                         ~~~~~~~~~~~~~~~~~~~~~~~~

node_modules/typescript/lib/lib.dom.d.ts:4872: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'.

4872 interface Element extends Node, ARIAMixin, Animatable, ChildNode, InnerHTML, NonDocumentTypeChildNode, ParentNode, Slottable {
               ~~~~~~~

node_modules/typescript/lib/lib.dom.d.ts:4872: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'.

4872 interface Element extends Node, ARIAMixin, Animatable, ChildNode, InnerHTML, NonDocumentTypeChildNode, ParentNode, Slottable {
               ~~~~~~~

node_modules/typescript/lib/lib.dom.d.ts:4922:14 - error TS2687: All declarations of 'tagName' must have identical modifiers.

4922     readonly tagName: string;
                  ~~~~~~~

node_modules/typescript/lib/lib.dom.d.ts:4953:101 - error TS2344: Type 'HTMLElementTagNameMap[K]' does not satisfy the constraint 'Element'.
  Type 'HTMLElement | HTMLAnchorElement | HTMLAreaElement | HTMLAudioElement | HTMLBaseElement | ... 63 more ... | HTMLFrameSetElement' is not assignable to type 'Element'.

4953     getElementsByTagName<K extends keyof HTMLElementTagNameMap>(qualifiedName: K): HTMLCollectionOf<HTMLElementTagNameMap[K]>;
                                                                                                         ~~~~~~~~~~~~~~~~~~~~~~~~

node_modules/typescript/lib/lib.dom.d.ts:8111:11 - error TS2430: Interface 'HTMLSelectElement' incorrectly extends interface 'HTMLElement'.

8111 interface HTMLSelectElement extends HTMLElement {
               ~~~~~~~~~~~~~~~~~

node_modules/typescript/lib/lib.dom.d.ts:14471: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'.

14471 interface Text extends CharacterData, Slottable {
                ~~~~

node_modules/@types/react/index.d.ts:2869: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'.

2869         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, Cache, CacheStorage, CloseEvent, Crypto, CryptoKey, DOMException, Event, EventListener, EventListenerOrEventListenerObject, EventTarget, File, FormData, Headers, HeadersInit, MessageEvent, PromiseRejectionEvent, ReadableStream, ReadableStreamDefaultReader, Request, Response, StreamPipeOptions, SubtleCrypto, TextDecoder, TextEncoder, TransformStream, URL, URLSearchParams, WebSocket, WebSocketEventMap, WritableStream, WritableStreamDefaultWriter, caches, console, crypto, 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:98: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'.

98   readonly body: ReadableStream | null;
              ~~~~

  node_modules/typescript/lib/lib.dom.d.ts:2444:14
    2444     readonly body: ReadableStream<Uint8Array> | null;
                      ~~~~
    'body' was also declared here.

node_modules/@cloudflare/workers-types/index.d.ts:223:3 - error TS2687: All declarations of 'publicKey' must have identical modifiers.

223   publicKey: CryptoKey;
      ~~~~~~~~~

node_modules/@cloudflare/workers-types/index.d.ts:223:3 - error TS2717: Subsequent property declarations must have the same type.  Property 'publicKey' must be of type 'CryptoKey | undefined', but here has type 'CryptoKey'.

223   publicKey: CryptoKey;
      ~~~~~~~~~

  node_modules/typescript/lib/lib.dom.d.ts:288:5
    288     publicKey?: CryptoKey;
            ~~~~~~~~~
    'publicKey' was also declared here.

node_modules/@cloudflare/workers-types/index.d.ts:224:3 - error TS2687: All declarations of 'privateKey' must have identical modifiers.

224   privateKey: CryptoKey;
      ~~~~~~~~~~

node_modules/@cloudflare/workers-types/index.d.ts:224:3 - error TS2717: Subsequent property declarations must have the same type.  Property 'privateKey' must be of type 'CryptoKey | undefined', but here has type 'CryptoKey'.

224   privateKey: CryptoKey;
      ~~~~~~~~~~

  node_modules/typescript/lib/lib.dom.d.ts:287:5
    287     privateKey?: CryptoKey;
            ~~~~~~~~~~
    'privateKey' was also declared here.

node_modules/@cloudflare/workers-types/index.d.ts:376:3 - error TS2687: All declarations of 'tagName' must have identical modifiers.

376   tagName: string;
      ~~~~~~~

node_modules/@cloudflare/workers-types/index.d.ts:377:12 - error TS2717: Subsequent property declarations must have the same type.  Property 'attributes' must be of type 'NamedNodeMap', but here has type 'IterableIterator<string[]>'.

377   readonly attributes: IterableIterator<string[]>;
               ~~~~~~~~~~

  node_modules/typescript/lib/lib.dom.d.ts:4873:14
    4873     readonly attributes: NamedNodeMap;
                      ~~~~~~~~~~
    'attributes' was also declared here.

node_modules/@cloudflare/workers-types/index.d.ts:379:12 - error TS2717: Subsequent property declarations must have the same type.  Property 'namespaceURI' must be of type 'string | null', but here has type 'string'.

379   readonly namespaceURI: string;
               ~~~~~~~~~~~~

  node_modules/typescript/lib/lib.dom.d.ts:4897:14
    4897     readonly namespaceURI: string | null;
                      ~~~~~~~~~~~~
    'namespaceURI' was also declared here.

node_modules/@cloudflare/workers-types/index.d.ts:430:84 - error TS2315: Type 'EventListener' is not generic.

430 declare type EventListenerOrEventListenerObject<EventType extends Event = Event> = EventListener<EventType> | EventListenerObject<EventType>;
                                                                                       ~~~~~~~~~~~~~~~~~~~~~~~~

node_modules/@cloudflare/workers-types/index.d.ts:434:70 - error TS2315: Type 'EventListenerOrEventListenerObject' is not generic.

434   addEventListener<Type extends keyof EventMap>(type: Type, handler: EventListenerOrEventListenerObject<EventMap[Type]>, options?: EventTargetAddEventListenerOptions | boolean): void;
                                                                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

node_modules/@cloudflare/workers-types/index.d.ts:435:73 - error TS2315: Type 'EventListenerOrEventListenerObject' is not generic.

435   removeEventListener<Type extends keyof EventMap>(type: Type, handler: EventListenerOrEventListenerObject<EventMap[Type]>, options?: EventTargetEventListenerOptions | boolean): void;
                                                                            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

node_modules/@cloudflare/workers-types/index.d.ts:641:3 - error TS2687: All declarations of 'kty' must have identical modifiers.

641   kty: string;
      ~~~

node_modules/@cloudflare/workers-types/index.d.ts:641:3 - error TS2717: Subsequent property declarations must have the same type.  Property 'kty' must be of type 'string | undefined', but here has type 'string'.

641   kty: string;
      ~~~

  node_modules/typescript/lib/lib.dom.d.ts:650:5
    650     kty?: string;
            ~~~
    'kty' was also declared here.

node_modules/@cloudflare/workers-types/index.d.ts:737:3 - error TS2687: All declarations of 'data' must have identical modifiers.

737   data: ArrayBuffer | string;
      ~~~~

node_modules/@cloudflare/workers-types/index.d.ts:737: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'.

737   data: ArrayBuffer | string;
      ~~~~

  node_modules/typescript/lib/lib.dom.d.ts:877:5
    877     data?: T;
            ~~~~
    'data' was also declared here.

node_modules/@cloudflare/workers-types/index.d.ts:838: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'.

838   redirect?: string;
      ~~~~~~~~

  node_modules/typescript/lib/lib.dom.d.ts:1513:5
    1513     redirect?: RequestRedirect;
             ~~~~~~~~
    'redirect' was also declared here.

node_modules/@cloudflare/workers-types/index.d.ts:1183:3 - error TS2687: All declarations of 'read' must have identical modifiers.

1183   read: number;
       ~~~~

node_modules/@cloudflare/workers-types/index.d.ts:1183:3 - error TS2717: Subsequent property declarations must have the same type.  Property 'read' must be of type 'number | undefined', but here has type 'number'.

1183   read: number;
       ~~~~

  node_modules/typescript/lib/lib.dom.d.ts:1701:5
    1701     read?: number;
             ~~~~
    'read' was also declared here.

node_modules/@cloudflare/workers-types/index.d.ts:1184:3 - error TS2687: All declarations of 'written' must have identical modifiers.

1184   written: number;
       ~~~~~~~

node_modules/@cloudflare/workers-types/index.d.ts:1184:3 - error TS2717: Subsequent property declarations must have the same type.  Property 'written' must be of type 'number | undefined', but here has type 'number'.

1184   written: number;
       ~~~~~~~

  node_modules/typescript/lib/lib.dom.d.ts:1702:5
    1702     written?: number;
             ~~~~~~~
    'written' was also declared here.

node_modules/@cloudflare/workers-types/index.d.ts:1238:42 - error TS2508: No base constructor has the specified number of type arguments.

1238 declare abstract class WebSocket extends EventTarget<WebSocketEventMap> {
                                              ~~~~~~~~~~~

node_modules/@cloudflare/workers-types/index.d.ts:1248:50 - error TS2508: No base constructor has the specified number of type arguments.

1248 declare abstract class WorkerGlobalScope extends EventTarget<WorkerGlobalScopeEventMap> {
                                                      ~~~~~~~~~~~

node_modules/@cloudflare/workers-types/index.d.ts:1278:102 - error TS2315: Type 'EventListenerOrEventListenerObject' is not generic.

1278 declare function addEventListener<Type extends keyof WorkerGlobalScopeEventMap>(type: Type, handler: EventListenerOrEventListenerObject<WorkerGlobalScopeEventMap[Type]>, options?: EventTargetAddEventListenerOptions | boolean): void;
                                                                                                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

node_modules/@cloudflare/workers-types/index.d.ts:1300:105 - error TS2315: Type 'EventListenerOrEventListenerObject' is not generic.

1300 declare function removeEventListener<Type extends keyof WorkerGlobalScopeEventMap>(type: Type, handler: EventListenerOrEventListenerObject<WorkerGlobalScopeEventMap[Type]>, options?: EventTargetEventListenerOptions | boolean): void;
                                                                                                             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


Found 41 errors.

Types appear to be only additive, not subtractive when compared with JS Fetch API types

The Issue

Some of the JS Fetch API is not implemented in Cloudflare Workers. One example of this is Body.blob() on a Request object, which is implemented in the JS Fetch API, but calling this function in a Cloudflare Worker will result in an error:

Failed to execute 'blob' on 'Body': the method is not implemented.

The Cloudflare Workers reference appears to agree (by omission) that Body.blob is not implemented:
https://developers.cloudflare.com/workers/reference/apis/request/

However, when using the Request type provided by the @cloudflare/worker-types repo, using Body.blob does not cause a type error and instead appears to be implemented:
Screen Shot 2020-07-21 at 2 57 17 PM

Inspecting the types in this repo, it seems that the definition of Request is purely additive (adding the cf property) and does nothing to prohibit unimplemented properties:

interface Request {
  cf: IncomingRequestCfProperties;
}

A Possible Solution

Before discovering the official types repo for Cloudflare Workers, I implemented TypeScript types for my Workers from scratch. In order to make the types for Cloudflare's Fetch API omit properties from the JS Fetch API, I defined custom types prefixed with Cf, for example:

export default interface CfRequest {
  readonly clone: () => CfRequest;
  readonly cf: CfObject;
  readonly bodyUsed: boolean;
  readonly headers: Headers;
  readonly method: RequestMethod;
  readonly redirect: RequestRedirect;
  readonly text: () => Promise<string>;
  readonly url: string;
}

By generating a custom type that inherits nothing from the official Fetch API types, unimplemented properties like Body.blob can be omitted.

Use `WorkerGlobalScope` inside `global` for binding.

The suggested way of accessing env is to create a binding.d.ts file with the following content.

declare global {
  const ENV_KEY: string
}

The problem with this approach is if the env variable is not declared the script just throws at runtime.

A better way would be to extent WorkerGlobalScope like below.

declare global {
  export interface WorkerGlobalScope {
    ENV_KEY: string
  }
}

This way the the env vars are accessed via the self object, thereby have flexibility for error handling and defaults.

Generic stream interfaces

Related to #116

It would be easier for packages to support Cloudflare workers and service workers if the stream interfaces matched. Any chance you could update ReadableStream, TransformStream, etc to be generic similar to the standard/web versions?

https://github.com/microsoft/TypeScript/blob/26aea0df613c61edfbfe7b003ff564bea421d071/lib/lib.dom.d.ts#L11917

Couple more I've encountered while migrating cfworker packages:

  1. Generic stream interfaces
  2. setTimeout should not require 3rd arg
  3. BufferSource type is missing (type BufferSource = ArrayBufferView | ArrayBuffer;)
    https://github.com/microsoft/TypeScript/blob/26aea0df613c61edfbfe7b003ff564bea421d071/lib/lib.dom.d.ts#L18678
    https://github.com/cfworker/cfworker/blob/6342b4653d56a0caa41c32090363354f63845b58/packages/cosmos/src/client.ts#L408
  4. RequestInfo type is missing (type RequestInfo = Request | string;)
    https://github.com/microsoft/TypeScript/blob/90600e1b17edb9072557816657254001a07c3ca0/lib/lib.webworker.d.ts#L5907
  5. FormData interface has incorrect iterable type:
    - [Symbol.iterator](): IterableIterator<([key: string, value: File | string])[]>;
    + [Symbol.iterator](): IterableIterator<[string, string | File]>;

`DurableObjectState` missing `name` property

DO states from DO that was generated with name are not being hinted at by the editor properly.

constructor(protected state: DurableObjectState, protected env) {
    let string = state.id.name; // type hints as error?
}

It should be defined as name?: string;

RequestInit and Request cf properties are different

RequestInit and Request cf properties are different, this makes using patterns like return new Request(parsedUrl.toString(), request) impossible because Request.cf is not structurally identical to RequestInit.cf.

I suggest we converge on a common cf type for both Request and RequestInit to support the above pattern.

HTMLRewriter typing

Incomplete typings of the HTMLRewriter:

interface ContentSettings {
    html: boolean;
}

interface ElementRewritableUnit {
    namespaceURI: string;
    append(content: string, settings?: ContentSettings): void;
    before(content: string, settings?: ContentSettings): void;
    after(content: string, settings?: ContentSettings): void;
    getAttribute(name: string): string | null;
    setAttribute(name: string, value: string): void;
    hasAttribute(name: string): boolean;
}

interface ElementContentHandlers {
    element(element: ElementRewritableUnit): void;
}

declare class HTMLRewriter {
    constructor();
    public on(selector: string, handlers: ElementContentHandlers): HTMLRewriter;
    public transform(response: Response): Response;
}

Add missing properties that can be in the `cf` object on an `event.request`

We should add missing properties that are documented here: https://developers.cloudflare.com/workers/reference/apis/request/

These should be added to the CfRequestProperties interface.

We should also update the interface to reflect that much of the geolocation information is optional, and may not be present on every request.

Missing properties:

  • clientTcpRtt
  • metroCode
  • isEuCountry (not documented yet)
  • weight
  • exclusive
  • group
  • group-weight

Unioned cf type on RequestInit does not allow re-assignment of properties

The unioned type introduced by PR #18 does not allow re-assignment of properties. Consider the following snippet:

// this assignment works just fine
let init: RequestInit = {
  cf: {
    cacheKey: 'foo',
  },
}

if (init.cf) {
  // but re-writing properties is prevented by the type checker
  init.cf.cacheKey = 'bar'
}

This produces the following type error:

image

The ideal outcome (if possible) would be to extend the RequestInit that fetch uses without obstructing the use case above while still supporting the example identified in issue #15.

Still trying to work out how to do this or if it's possible, but wanted to start a discussion around it :)

cache types

wondering whether cache types will be added here in future?

KVNamespace declared differently than other interfaces

Why is the KVNamespace declared differently than the rest of the interfaces?

workers-types/index.d.ts

Lines 443 to 444 in 6340625

declare module '@cloudflare/workers-types' {
export interface KVNamespace {

Would it be better to reference the types like this?

{
  "extends": "../../tsconfig-base",
  "compilerOptions": {
    "target": "esnext",
    "lib": ["webworker", "esnext"],
    "composite": false,
    "types": ["@cloudflare/workers-types"]
  }
}

Just thinking the instructions in the README are strange with respect to the empty import:

Usage
Just supply an empty import in one of your source files to receive the workers types

import {} from '@cloudflare/workers-types'

Might be considered an unused import by formatters/linters.

ReferenceError: Request is not defined

Having the strangest behaviour that I can't get to the bottom of since trying v2.0.0 of this module.

Given this really simple module, worker.ts:

export default async function handleRequest(
  request: Request
): Promise<Response> {
  const newRequest = new Request(request)
  const defaultScore = 99
  newRequest.headers.set(
    'Cf-Bot-Score',
    (request.cf.botManagement?.score || defaultScore).toString()
  )
  return fetch(newRequest)
}

And this really simple mocha test: worker.test.ts:

import handleRequest from 'lib/worker'
describe('Worker', () => {
  it('should map the bot score to a request header', async () => {
    const request = {
      cf: {
        botManagement: {
          score: 50
        }
      }
    } as Request
    const result = await handleRequest(request)
    console.log(result)
  })
})

And the following tsconfig:

{
  "compilerOptions": {
    "types": ["@cloudflare/workers-types", "mocha"],
    "module": "CommonJS",
    "target": "es2020",
    "lib": ["es2017", "WebWorker"],
    "rootDir": "./",
    "outDir": "./built",
    "baseUrl": "./",
    "allowJs": true,
    "checkJs": true,
    "alwaysStrict": true,
    "noImplicitAny": false,
    "noImplicitThis": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "strictPropertyInitialization": true,
    "noEmitOnError": false,
    "sourceMap": false
  },
  "include": ["lib/**/*.ts", "test/**/*.ts"],
  "exclude": ["node_modules"]
}

In the GUI (vscode) all intellisense is working fine, and typescript compiles fine too.

However, when running the tests via Mocha, I get:

❯ ./node_modules/.bin/mocha -r ts-node/register -r tsconfig-paths/register test/index.test.ts 
  Worker
    1) should map the bot score to a request header

  0 passing (9ms)
  1 failing

  1) Worker
       should map the bot score to a request header:
     ReferenceError: Request is not defined
      at Object.handleRequest [as default] (lib/worker.ts:4:22)
      at Context.<anonymous> (test/index.test.ts:11:39)
      at processImmediate (internal/timers.js:458:21)

So specifically on the line:

const newRequest = new Request(request)

Therefore it seems fine with the interface use in the function parameters:

export default async function handleRequest(
  request: Request
): Promise<Response> {

Any ideas?

Promise types aren't parameterized properly

Do a quirk of the way we auto-generate types and changes to the runtime, we accidentally are not specifying the return type of promises. This will be fixed in the runtime but just opening this here as a tracking issue.

Module workers `fetch` handler missing definitions—no `Context` argument?

Working on wiring up toucan-js to a modules worker, and got stuck on needing a FetchEvent. Turns out that's already been udpated, see robertcepa/toucan-js#72 (comment)

in .mjs workers, waitUntil is provided by runtime in ctx object that is passed into fetch as the third argument. Here's an example:

The problem is there's no (that I can see) definition for ctx, or anything for the export default fetch(request, env, ctx) function at all. Toucan provides this:

export declare type Context = {
    waitUntil: (promise: Promise<any>) => void;
    request?: Request;
};

So you can workaround this using:

import { Context } from 'toucan-js/dist/types'

But I don't know if that's the full type definition. What else is provided on ctx at the moment?

get can return undefined

get<T = unknown>(key: string): Promise<T> should really be: `get<T = unknown>(key: string): Promise<T | undefined>;

BSD-3 License

👋

Thanks to everyone who's contributed as workers-types has evolved from one Cloudflare employee's project to a community project fully supported by the Workers team!

We will be releasing the workers-types repo under the 3-Clause BSD license ("BSD-3"), so we are asking all non-Cloudflare employees who have already contributed to workers-types to license their contributions under BSD-3. The relevant PR is #30 .

If you agree, please add a comment below stating "I hereby license all my contributions to workers-types under BSD-3."

Contributors we'd like to hear from are:

FetchEvent constructor no longer accepts second argument

Problem

According to the FetchEvent spec the FetchEvent constructor accepts an optional second argument called init. I think this worked in 2.2.1 but stopped working in 3.0.0.


Motivation:

I'm using the init.request argument in my tests like so

new FetchEvent("fetch", {
  request: new CfRequest("/foo", { method: "GET" }),
})

to test the handler passed to addEventListener("fetch", (event) => {}) with a fake event. This creation of the fetchEvent now being marked as invalid by TypeScript.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.