Obtain precise data type from validated class

I have a Typescript class that is capable of being validated, resulting in guaranteed field types. However, the class must also be able to accept user input. Is it possible to extract a strict type from this permissible class?

Simplified: I have a class with an implicit interface of {value: string | undefined} and I am seeking a way to derive {value: string} automatically. Is this feasible?

To provide more context, here is an example of such a class:

class Validatable {
  value: string | undefined = undefined
}

(In my actual implementation, it needs to be a class due to validation requirements, but the specifics of validation are not relevant for this query)

This class can undergo validation as follows:

function getValid (inst: Validatable) {
  const errors = validate(inst)
  if (errors.length > 0) throw new Error("Invalid")
  return inst
}

const inst = new Validatable()
inst.value = "foo"
getValid(inst).value
                ^-- at this point, the type is string | undefined 
                    however, we know it should be strictly a string

What I aim to achieve is an automatic derivation of the strict interface {value: string}. Is this within the realm of possibility?

Answer №1

To eliminate all instances of | undefined from a data type, you can utilize a mapped type:

class Validatable {
  value: string | undefined = undefined
}
type RequiredNotNullOrUndefined<T> = {
  [P in keyof T]-?: Exclude<T[P], null | undefined>
}

function getValid (inst: Validatable) {
  return inst as RequiredNotNullOrUndefined<Validatable>  // <-- field type is now guaranteed
}

const inst = new Validatable()
inst.value = "foo"
getValid(inst).value // returns string

Playground

Please note: While the RequiredNotNullOrUndefined type is similar to the built-in Required type, the latter only removes optionality from a type and does not eliminate | undefined | null from any property type, unlike this version.

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

Declaring a function in TypeScript triggers an error notification

I encountered a typescript error while running my code stating that "require" is not a function. To resolve this, I declared the function beforehand; however, a new typescript error now occurs saying "Modifiers cannot appear here." Can anyone assist me w ...

NextJS and AWS Amplify collaboration for secure authentication routing

After hours of research, I'm struggling to navigate the authentication routing in NextJS combined with AWS Amplify. As a newcomer to NextJS, I want to implement a feature that disables the login/register page for users who are already logged in and pr ...

Loop through the JSON response and calculate the total bill using TypeScript

Having trouble calculating the total sum of bills in an order list using typescript. The error message 'Object is of type 'unknown' keeps popping up when trying to access the total bill field. Interestingly, it works fine in the browser cons ...

I'm curious about the origins of the "readme" field within the artifact registry file

Within our private npm registry on Azure, we house our own npm package alongside the npmjs packages. One particular package, @typescript-eslint/parser, has caused our pipelines to fail during the npm install task due to a SyntaxError: Unexpected end of JSO ...

Transforming the timestamp to a date object using Angular and Typescript

As a newcomer to Angular 2.0, I've been delving into new concepts in order to grasp it better. However, despite encountering this common issue multiple times and reading through various solutions, I haven't been able to find the answer to my prob ...

Retrieve the 90 days leading up to the current date using JavaScript

I've been searching for a way to create an array of the 90 days before today, but I haven't found a solution on StackOverflow or Google. const now = new Date(); const daysBefore = now.setDate(priorDate.getDate() - 90); The result I'm looki ...

Angular Cesium.js Integration: Exploring the Power of Injection Tokens

Currently, I'm exploring how to utilize the cesium.js library in an angular-friendly manner to continue working with typescript. While following tutorials on integrating 3rd party libraries, I am attempting to inject dependencies using a dependency to ...

Collection of personalized forms where the parent is a FormGroup

One scenario I'm working on involves creating multiple custom formgroup classes that have FormGroup as their parent class, structured like this: export class CustomFormGroup1 extends FormGroup { //custom properties for this FormGroup const ...

Unspecified data stored within an object

I am looking to populate a page with data from the server and have the ability to update the information. To achieve this, I am using formbuilder to fetch data from the server as the default value. Here's how I am implementing it: createForm(){ ...

Is there a way to retrieve information from my personal API using redux?

I am having trouble retrieving data from my own API using Redux. When I make the API call, I receive an empty object and I cannot figure out why this is happening. The API itself was built using express.js and MongoDB and works perfectly fine when tested w ...

Route mismatch

It's showing an error message saying it can't match any routes, but I have clearly defined the route I'm using here: { path: 'categories', component: CategoriesComponent, }, { path: 'categories/:id', ...

Invoke a function within a v-if directive in a Vue.js script

I'm relatively new to working with vue.js and I have a small issue that I need help with. Within my vue.js file, there is an existing method called doSomething(): doSomething(){ //updates few properties here } I also have a list or array as a com ...

I am encountering difficulties in accessing my component's property within the corresponding template while working with Angular 5

When I call an HTTP POST method to retrieve table names from the backend, I attempt to display them in the template using ngFor. However, the table names are not appearing on the screen. The tNames property is inaccessible in the template. As a beginner i ...

Exploring the possibilities of updating carousel items in Angular using Bootstrap

I'm working on a project where I have 4 images and a carousel that needs to navigate to the respective index when one of the images is clicked. The challenge is that the carousel is built with Bootstrap and jQuery, but the rest of the application is A ...

Navigating between components in angular2 modules: A tutorial

Currently, I am utilizing angular2 Final version for my development tasks. Within my project, I have established 3 distinct modules: AppModule ProjectModule DesignerModule In the past, I solely had AppModule which integrated the following RoutingModule ...

Eliminate attributes from an object that are not defined within a specific type interface

I am trying to filter out properties from an object that are not defined in a specific type interface. Suppose I have the following interface: export interface CreateCustomerUserInput { fullname: string; email: string; } And this is my initial o ...

Step-by-step guide on uploading a file for API testing

When working on API integration tests using playwright, I encounter a scenario where I need to call an API that uploads a file. In my project directory, there is a folder dedicated to static assets which contains the following file: /static-assets - im ...

Is it possible for TypeScript to manage a dynamic return type that is not determined by a function parameter?

I am facing a challenge with dynamic type checking using a param type and seeking help to solve it. Even though it might be a difficult task, any assistance would be greatly appreciated! Consider the following code: class DefaultClass { defaultProp: n ...

An extremely basic inquiry regarding JavaScript form validation

Is there a way to add a simple icon next to a form field when users type in their name or email address? I only want the icon to show if even one character is typed. The icon should change based on whether the field has content (success) or not (fail). L ...

What is the process for transforming an exported function into a function type?

When writing Express middleware, I am facing challenges in deciding how to properly typecast my functions. For instance, when working on an error handler: export function errorHandler(err, req, res, next) { ... } TypeScript correctly points out that th ...