What is preventing the exclusion of the null type in this specific situation within Typescript?

type NonNullableCopy<O> = {
    [p in keyof O] -?: O[p] extends null | undefined ? never : O[p];
};

type Adsa = {a?: number | null}
type Basda = NonNullableCopy<Adsa>
let asd : Basda = {
    a: null // Still valid. No errors
}

Although it seems similar, the following code:

type NonNullable<T> = T extends null | undefined ? never : T;

type NonNullableCopy<O> = {
    [p in keyof O] -?: NonNullable<O[p]>;
};

type Adsa = {a?: number | null}
type Basda = NonNullableCopy<Adsa>
let asd : Basda = {
    a: null // Works, but throws errors
}

There is actually a key difference between these two blocks of code. Can you spot it? Please explain to me. Thank you.

Answer №1

One kind of type

type NonNullable<T> = T extends null | undefined ? never : T;

is referred to as a distributive conditional type, specifically when the checked type T is a simple generic parameter. Distributive types evaluate each member in a union individually, resulting in a new union for the overall type processing. For example, NonNullable<A | B | C> translates to

NonNullable<A> | NonNullable<B> | NonNullable<C>
.

Distributive types are handy for filtering unions by examining each member. When dealing with something like string | undefined, only relevant parts are evaluated, allowing for precise filtering of the union.


In contrast, another type

type Different<O, P extends keyof O> = O[P] extends null | undefined ? never : O[P];

does not fall under the distributive category. The complexity of the type expression O[P], involving multiple parameters and indexed access, leads to non-distributive behavior. In this case, Different<O, P | Q | R> will not behave equivalently to

Different<O, P> | Different<O, Q> | Different<O, R>
.

If O[P] represents string | undefined, the evaluation results in

(string | undefined) extends (null | undefined)
, which respects the input without restructuring based on a union breakdown.


Check out this Playground link for code samples

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

The user model cannot be assigned to the parameter of type Document or null in a mongoose with Typescript environment

While working with Typescript, I encountered an error related to mongoose. The issue arises from the fact that mongoose expects a promise of a mongoose document (in this case, the user's document) or "null" to be resolved during a search operation. Ho ...

How to invoke a function from a different controller in Ionic 2

Is it possible to call a function in another controller within Ionic 2? Here is my code where I want to call the loadPeople function in the tab controller. home.ts import { Component } from '@angular/core'; import { NavController } from ' ...

The NGINX reverse proxy fails to forward requests to an Express application

I am currently in the process of setting up a dedicated API backend for a website that operates on /mypath, but I am encountering issues with NGINX not properly proxying requests. Below is the nginx configuration located within the sites-enabled directory ...

One issue that may arise is when attempting to use ngOnDestroy in Angular components while rearranging user transitions

Encountered an issue recently with Angular - when the user navigates from component A to component B, component A remains active unless ngOnDestroy is triggered. However, if the user visits component B before going to component A and then leaves, ngOnDes ...

TS type defined by JS constants

I am currently working on a project that involves both JavaScript and TypeScript. I am trying to find a solution to reduce code duplication when using JavaScript string constants by converting them into TypeScript types. For example, let's say I have ...

Nuxt3 - TS2339: The 'replaceAll' property is not found on the 'string | string[]' type in Nuxt3

Hey there! I've been experimenting with the replaceAll() method within my Nuxt3 project and encountered a strange error. Folder Structure ───pages │ └───Work │ │ index.vue │ │ [Work].vue Template <templat ...

InitAuth0 Auth0 encountering deepPartial error in Next.js with TypeScript setup

Having some trouble setting up auth0 with nextjs using typescript. When I try to initialize Auth0, I encounter an error regarding deep partials, Argument of type '{ clientId: string; clientSecret: string; scope: string; domain: string; redirectUri: st ...

Tips for implementing self-managed state in Vue.js data object

My approach in organizing my Vue application involves using classes to encapsulate data, manage their own state (edited, deleted, etc), and synchronize with the back-end system. However, this method seems to conflict with Vue in some respects. To illustra ...

Steps to resolve the issue of 'type is not assignable to any' while working with a member

I'm facing an issue with a code snippet like the one below: interface IFoo { bar: string; baz: number; } function f(foo: IFoo, name: 'bar' | 'baz', val: any) { foo[name] = val; // <<< error: Type 'any' i ...

typescript Can you explain the significance of square brackets in an interface?

I came across this code snippet in vue at the following GitHub link declare const RefSymbol: unique symbol export declare const RawSymbol: unique symbol export interface Ref<T = any> { value: T [RefSymbol]: true } Can someone explain what Re ...

Accelerated repository uses TypeScript to compile a node application with dependencies managed within a shared workspace

Struggling to set up an express api within a pnpm turborepo workspace. The api relies on @my/shared as a dependency, which is a local workspace package. I have been facing challenges in getting the build process right. It seems like I need to build the s ...

Develop a user interface that includes the ability to have unspecified properties of an unspecified data type,

interface Sample { value?: string [prop: string]: any } const sampleObject: Sample = { title: 'John' } const data = sampleObject.title By including "any" in the interface, it eliminates the automatically assumed "string" type for the p ...

Converting a string to a Date in Angular2 using Typescript

I need to initialize a new Date object using a specific date. I have considered converting it from a particular string, like so: let dateString = '1968-11-16T00:00:00' How can I achieve this in typescript? Update: I am specifically looking fo ...

Passing events from a parent component to dynamically created child components in Angular

UPDATE: I've decided to tackle this issue in a different way by retrieving dynamic child component values in the parent component's save() function, following the accepted answer. I am attempting to create a system where a parent component emits ...

Steps for updating a server component after redirectionWould you like to know how

One of my server components fetches and displays data only when the user is authorized: function CheckAuthorization() { const isAuthenticated = // check if user is authorized return ( <div> {isAuthenticated ? ( <DisplayAutho ...

Perform an action after the Ngx Bootstrap modal has been hidden

My modal features a login button: <button type="button" (click)="save()" class="btn btn-primary"> login </button> Upon clicking the button, my desired outcome is to: first hide the modal, and second navigate to another route. However, ...

Typescript - Conditional imports

When working with the moment-timezone module, one issue that arises is receiving a warning if it is included multiple times. In my specific case, I have a module that necessitates the use of this timezone functionality. Since I am unsure whether or not the ...

The JSON object, which has been converted into a string and sent over the network,

Attempting to set up a websocket server using TypeScript in Node.js, the following code was used: ws.on('message', (msg: string) => { console.log("got message:" + msg); const m = JSON.parse(msg); console.log(m); ...

Instructions on invoking a function from another Material UI TypeScript component using React

In this scenario, we have two main components - the Drawer and the AppBar. The AppBar contains a menu button that is supposed to trigger an event opening the Drawer. However, implementing this functionality has proven challenging. I attempted to use the li ...

The specified React element type is not valid

Currently working on a web application using Typescript, Electron, Webpack, and NodeJS, but encountering issues with the import/export functionality. The error message that I am facing reads: "Warning: React.createElement: type is invalid -- expect ...