Typescript broadens the scope of objects while filtering out the inclusion of the

Is there a way to specifically exclude the Date type from being considered as part of the object type? I am encountering an error in my form validation where the Date type is causing issues within objects.

export type FieldErrors<FormValues> = {
  [Key in keyof FormValues]?: FormValues[Key] extends any[]
    ? FormValues[Key][number] extends object
      ? FieldErrors<FormValues[Key][number]>[]
      : FieldError
    : FormValues[Key] extends object // this is the issue bit when extend object
    ? FieldErrors<FormValues[Key]>
    : FieldError
};


type FormData = {
  stringField: string;
  numberField: string;
  dateField: Date;
};

{errors.dateField && errors.dateField.message} // This results in an error because Date type is considered an object

Answer №1

Looking for a negated type such as

FormValues[Key] extends object & not Date
is currently unavailable.

Instead, you can incorporate a conditional step to verify the presence of Date. Since Date is more specific than object, this validation should precede the FormValues[Key] extends object evaluation.

The recommended approach is to proceed from the most precise to the most general scenario. Take a look at the following example:

interface FieldError { message: string }

export type FieldErrors<FormValues> = {
    [Key in keyof FormValues]?: FormValues[Key] extends any[]
    ? FormValues[Key][number] extends object
    ? FieldErrors<FormValues[Key][number]>[]
    : FieldError
    : FormValues[Key] extends Date // check for Date conditionally first
    ? FieldError
    : FormValues[Key] extends object 
    ? FieldErrors<FormValues[Key]>
    : FieldError
};

/*
type MyFormErrors = {
  stringField?: FieldError | undefined;
  numberField?: FieldError | undefined;
  dateField?: FieldError | undefined;
}
*/
type MyFormErrors = FieldErrors<FormData>

declare const errors: MyFormErrors
errors.dateField && errors.dateField.message // FieldError.message: string

Playground

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

Passing along the mouse event to the containing canvas element that utilizes chart.js

Recently, I created a custom tooltip for my chart.js chart by implementing a div that moves above the chart. While it works well, I noticed that the tooltip is capturing mouse events rather than propagating them to the parent element (the chart) for updati ...

Yep, identifying InferType optional attributes

Here's an example of a Yup schema I created to fetch entities known as Parcels: export const FindParcelsParamsSchema = Yup.object({ cursor: Yup.number().optional(), pageSize: Yup.number().positive().integer().optional(), }); All fields are option ...

The TypeScript type 'Record<string, string>' cannot be directly assigned to a type of 'string'

I can't seem to figure out why this code isn't working. I've encountered similar issues in the past and never found a solution. The snippet goes like this: type dataType = { [key: string]: string | Record<string, string>; ...

Unable to show the input's value

Need help in taking user input to display calculated values //html <div class="empty"> <h5> Enter Empty Seats </h5> <ion-item> <ion-input placeholder="Enter Number of Empties.." type="number" name="emptySeats" [( ...

Avoiding the inclusion of server-side modules in the webpack build process for a client-side application

I specialize in developing web applications using NodeJS and React. Lately, I've been experimenting with different architecture styles and I'm currently fascinated by the concept of sharing code between the server-side and client-side. I believe ...

What steps can I take to stop my embedded YouTube video from constantly refreshing?

Is there a way to stop my embedded YouTube video from constantly refreshing? I have tried multiple methods, but they all seem to result in an error that causes the video to keep reloading. getVideoUrl(FileUrls) { if (this.loadApiDone == true) { ...

What are the best ways to work with LatLng objects?

When I run a request to retrieve data from a database, the response displayed in the console using JSON.Stringify() is as follows: sites : [{"siteName":"Site de Marseille", "siteAdress1":"rue du string", "siteAddress2":"string", "siteCodPost":"13010","sit ...

What causes the loss of type inference for the object literal in this mapped type?

Although contrived, I usually pass an object literal to a function and capture the values of the literal in a generic format, like this: type Values<V> = { a: V; b: V; }; function mapValues<V>(v: Values<V>): V { return v as any; / ...

When creating utility classes, is it beneficial to offer a non-mutable API to facilitate their integration with frameworks such as React?

Currently, I am working on enhancing the functionality of my DateWithoutTime class. As part of this process, private fields within the class need to be updated by public methods. this.state.dateWithoutTimeInstance.shiftBySpecificDaysCount({ daysCount: 5, ...

Having an issue in Angular 2 where the correct function is not triggered when a button is placed within a selectable anchor

Within an anchor element, I have a button that triggers its own click listener for an editing popup module. The anchor itself has another click listener assigned to it. For example: <a (click)="onClick(myId)" class="list-group-item clearfix"> < ...

Dealing with reactive form controls using HTML select elements

I am working with a template that looks like this: <form [formGroup]="form"> <mdl-textfield type="text" #userFirstName name="lastName" label="{{'FIRSTNAME' | translate}}" pattern="[A-Z,a-zéè]*" error-msg ...

Utilize an Immediately-Invoked Function Expression (IIFE) class in TypeScript

In an attempt to create a model class with privacy, I have implemented a class with closures in the Answer model file: export class Answer { getId; getText; constructor(id: string, text: string) { const idPrivate = id; const textPrivate = t ...

You are unable to assign to 'total' as it is a constant or a property that cannot be modified

Upon running ng build --prod in my project, I encountered the following error: src\app\components\xxxx\xxxx.component.html(116,100): : Cannot assign to 'total' because it is a constant or a read-only property. The proble ...

Using optional chaining with TypeScript types

I'm dealing with a complex data structure that is deeply nested, and I need to reference a type within it. The issue is that this type doesn't have its own unique name or definition. Here's an example: MyQuery['system']['error ...

Encountering an issue with importing react-relay-network-modern in Cypress

The Challenge Hello everyone, I am currently working with TypeScript 3.0.3 and cypress, and I'm facing an issue while trying to import the react-relay-network-modern module in my component. Despite having the module present in my node_modules folder ...

Challenges encountered when using promises for handling mysql query results

I've been working on creating a function that will return the value of a mysql query using promises. Here's what I have so far: query(query: string): string { var response = "No response..."; var sendRequest = (query:string): Prom ...

Unreachable Angular data without using subscribe

I am facing an issue with Angular 2 (apologies for my limited English proficiency...). I need to be able to modify a component variable from another component. The trouble is, this component variable remains undefined outside the subscribe function even t ...

Choosing options using an enum in Angular 2

In my TypeScript code, I have defined an enum called CountryCodeEnum which contains the values for France and Belgium. export enum CountryCodeEnum { France = 1, Belgium = 2 } Now, I need to create a dropdown menu in my form using this enum. Each ...

Is it possible to implement a different termination condition when using *ngFor in Angular 2?

After countless hours of searching on Google, I have yet to discover a method for implementing an alternative stop condition for loops created with the *ngFor directive. By default, *ngFor loops end with this condition: index < array.length. Is there a ...

TypeScript - ESBuild - Encountered an unexpected '<' token

When compiling TypeScript files for a React app with esbuild, everything goes smoothly. However, upon checking the browser console, an error pops up: An unexpected token '<' is causing errors after the return statement // components/editor/ ...