Creating TypeScript code that allows for accessing properties of a TypeScript object that may be undefined

I am looking to create a custom type that allows access to undefined properties of an object with the type of any, and does so recursively. To better illustrate the issue, I have included a simplified and corrected example below based on feedback received.

const data = {a: "a", b: {c: 'hey'}}

type Data = typeof data & { [key: string]: any }

const dataOptional: Data = data

// This errors:) as expected, because the property "a" does not have such method
dataOptional.a.nonExistentStringMethod
// These do not error:) as expected, because d has the correct type of "any"
dataOptional.d
dataOptional.d.nonExistentStringMethod
// This does error:( highlighting the problem with this type
dataOptional.b.d

The issue with the current implementation is that it does not apply recursively. It is important to note that I start with the JSON value of data and need to generate TypeScript code that allows me to export the original data in a way that enables accessing undefined properties as described above.

So my question is, how can I transform a JSON value into TypeScript code that exports the JSON value in a manner where I can recursively access any undefined property with the value of any, while preserving typing information for defined properties within the original object?

Answer №1

If you are looking to modify object types in TypeScript, consider using this utility function:

type WithAny<T> = {
  [key: string]: any;
} & {
  [key in keyof T]: T[key] extends object ? WithAny<T[key]> : T[key]
}

This utility function will recursively combine the given type with an index type that sets all string keys to have a value of any. It maintains the typing for known keys without affecting their specificity.

For example:

const data = {
  a: "a",
  b: {
    c: "hey",
  },
}

type AnyData = WithAny<typeof data>

const anyData: AnyData = data

anyData.a.foo // Will result in an error
anyData.b.foo // Will not throw an error

/*
Pseudo-type of AnyData:
{
  a: string
  b: {
    c: string
    [key: string]: any
  }
  [key: string]: any
}
*/

TypeScript playground


Note of Caution

Be aware that this utility function intersects with any object type, including built-in objects like Date, Map, etc. If your data contains these types, they will also be affected by the intersection.
If you know the specific object types in your data, make sure to update the extends check to exclude them. Proceed with caution when implementing the provided code if you are unsure about the data structure.

For handling Date objects, you can customize the WithAny type as follows:

type WithAny<T> = {
  [key: string]: any
} & {
  [key in keyof T]: T[key] extends object
    ? T[key] extends Date
      ? T[key]
      : WithAny<T[key]>
    : T[key]
}

You can extend these checks further by nesting them where necessary.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to generate JSON requests in Objective-C?

I'm excited about a framework I've found, but I'm struggling with creating requests. Most tutorials focus on downloading and parsing Json data, while I need help building a Json request, sending it, and parsing the response. Does anyone hav ...

Changing Array into a JSON Document

I have been utilizing JSONKit to transform the data stored in my .json file into an NSMutableArray. I am now looking for a way to revert this array back to JSON data and save it back to the file. Are there alternative Kits or methods that could achieve t ...

What are the most efficient methods for extracting information from tables on Wikipedia and converting the data and links into JSON format?

I am relatively new to web development and have a question regarding extracting data from Wikipedia. I am working on a personal web application that will catalogue past UFC events. Unfortunately, I have not been able to find an open-source API with detai ...

Processing and handling XML and JSON requests and responses in Spring MVC

For my project, I need to create a REST service that can accept input in either XML or JSON format through the POST method, and return output in the same format as the input. I initially attempted a specific approach to achieve this functionality, but enco ...

Error in Angular: Http Provider Not Found

NPM Version: 8.1.4 Encountered Issue: Error: Uncaught (in promise): Error: Error in ./SignupComponent class SignupComponent_Host - inline template:0:0 caused by: No provider for Http! Error: No provider for Http! The error message usually indicates the a ...

Error: The use of await in RequestPromise is not valid

I encountered a TSLint error stating "Invalid 'await' of a non-Promise value." in the line of code below: const response: RequestResponse = <RequestResponse>await this.apiRequest(uri); Additional code context: private apiRequest: Request ...

Sending PHP variable to jQuery using POST

To keep track of page referrals, I often use URLs like this: www.example.com/?ref=google Once I've captured the referral as a variable, it looks like this: if ($_GET['ref'] !== "") { $ref = $_GET['ref']; } else { $ref = ...

Is there a way to inform TypeScript that the process is defined rather than undefined?

When I execute the code line below: internalWhiteList = process.env.INTERNAL_IP_WHITELIST.split( ',' ) An error pops up indicating, Object is possibly undefined. The env variables are injected into process.env through the utilization of the mod ...

SonarQube seems to be overlooking TypeScript files with the .ts extension

I'm currently setting up SonarQube on Jenkins for an Angular 2 project, but I'm facing an issue where Sonar isn't recognizing the TypeScript files with the .ts extension. Here's the current configuration: sonar.projectKey=App Name- An ...

How can we effectively map Typescript Enums using their keys without relying on a Map?

Consider the following Enum instances: export enum TopicCategories { GUIDES = 'Guides', TASKS = 'Tasks', CONCEPTS = 'Concepts', FORMULAS = 'Formulas', BLOGS = 'Blogs' } export enum Top ...

Converting a JSON array containing multiple arrays into a SQL table

I received a JSON response from an API that looks like this: { "series":[ { "series_id": "SER_ID_1", "data": [ ["20200101", 1.0 ], ["20200102" ...

Potential absence of object.ts(2531)

Currently, I am working on a project using Node.js with Typescript. My task involves finding a specific MongoDB document, updating certain values within it, and then saving the changes made. However, when I try to save the updated document, an error is bei ...

Showing Nested Numerical Objects Post RequestBeing Made

Currently, I am facing an issue with accessing nested objects referred to by numbers. After making a service call to retrieve a JSON object, I mapped each field to another object which will be used for displaying the fields in HTML. The problem arises whe ...

What is the process for accessing the value of a property within the parent's generic type using a key?

Describing this concept can be somewhat challenging, so I'll just present the code instead: type FormFields = { email: string; count: number; }; type FieldMap<T extends Record<string, unknown>> = Record< keyof T, FieldMapping&l ...

The error message "Property 'name' is not found in type 'RepositoryResponse[]'" is being displayed by Typescript

I am encountering an issue while attempting to retrieve data from the GitHub API. The error message indicates that values from the API are not present in the interface. API URL: interface Repository { name: string; avatar_url: string; ...

What is the best way to transform a socket message into a JSON format using Python?

When a web request comes in, I receive a string with the code below: data_from_flask = c.recv(2048).decode('utf8') The message is displayed as: 'GET / HTTP/1.1\r\nHost: localhost:31477\r\nConnection: keep-alive\r&b ...

Transforming JSON data into a visual flowchart using VUE.js

In the project I am currently working on, I am faced with the challenge of importing a JSON file (exported from a flowchart drawing project) and converting its data into an actual flowchart. Unfortunately, I have not been able to find any leads on how to c ...

Utilizing Typescript and sinon to mock the functionalities of jsonwebtoken

Looking for help with mocking the function verify in Typescript's jsonwebtoken library. I've installed typescript, jsonwebtoken, sinon, mocha, and chai along with their corresponding types. However, when trying to stub the function, an error occu ...

The TCP server is cutting off the received message from the network stream

My TCP listener implementation looks like this: Using client As TcpClient = _server.AcceptTcpClient() Threading.ThreadPool.QueueUserWorkItem(AddressOf NewClient) Using ns As NetworkStream = client.GetStream() ...