Home > Software design >  Multidimensional json typing
Multidimensional json typing

Time:11-04

I have the following initial json:

let options = {cf: { image: {} } }

I need to add new elements inside the images key as per the checks below:

  if (url.searchParams.has("fit")) options.cf.image.fit = url.searchParams.get("fit")
  if (url.searchParams.has("width")) options.cf.image.width = url.searchParams.get("width")
  if (url.searchParams.has("height")) options.cf.image.height = url.searchParams.get("height")
  if (url.searchParams.has("quality")) options.cf.image.quality = url.searchParams.get("quality")

The problem is that it returns that the type "fit", "width", "height", "quality" does not exist in the options.cf.image element (example below):

Property 'fit' does not exist on type '{}'.ts (2339)

I tried to create an interface for cf.image with the elements being optional but it didn't work because it returns that the element can be null and it can't because it's a string.

In the end, I need the options to be sent to the fetch(URL, options) function, where options is of type RequestInit | Request

My complete code is at https://pastebin.com/fvvBpf1e. It is Cloudflare's open source for resizing images https://developers.cloudflare.com/images/image-resizing/resize-with-workers/#an-example-worker

CodePudding user response:

The problem is let options = {cf: { image: {} } } defines options with the type { cf: { image: {}; }; }, which means TypeScript expects the image key to only contain an empty object {}.

You can add these keys to your options definitions with suitable defaults, or define an interface for options that appropriately types it.

For example,

// These may not be suitable defaults, but just to illustrate
let options = { cf: { image: { fit: '', width: '', height: '', quality: '' } } }

will compile because typescript knows cf.image.fit should exist and has a type.

An interface solution may look like:

interface Options {
    cf: {
        image: { 
            // fit? means this type is `string | undefined` 
            fit?: string;
            width?: string;
            height?: string;
            quality?: string;
        }
    }
}

let options: Options = { cf: { image: {} } }

CodePudding user response:

You posted a link to the documentation of CloudFlare. Reading it can be a good idea:

RequestInitCfProperties:

An object containing Cloudflare-specific properties that can be set on the Request object. For example:

// Disable ScrapeShield for this request.
fetch(event.request, { cf: { scrapeShield: false } })

Invalid or incorrectly-named keys in the cf object will be silently ignored. Consider using TypeScript and @cloudflare/workers-types to ensure proper use of the cf object.

You can inspect the desired type in RequestInitCfProperties source code

So the correct type of options is:

interface CloudFlareFetchOptions {
    cf: RequestInitCfProperties
}
  • Related