Why would someone use "extends an empty object" in TypeScript?

Explain the distinction between

class Document<T extends {}>{}
and class Document<T>{}

Can you provide examples to illustrate the difference?

Answer №1

A generic type parameter with no specific constraint is considered unconstrained, or has an implicit constraint to the unknown type to which all types are compatible. Therefore, in the examples like class Document<T>{} or

class Document<T extends unknown>{}
, any type can be assigned to T:

class Document<T>{ /**implementation involving T**/ }
new Document<{ a: string }>(); // valid
new Document<string>(); // valid
new Document<null>(); // valid
new Document<undefined>(); // valid
new Document<string | undefined>(); // valid

On the contrary, T extends {} limits T to the so-called "empty object type" {}, which includes any object type or primitive type that behaves like an object when indexed into it. If JavaScript automatically wraps a primitive type with a wrapper object, then that primitive type is assignable to {}.

The only primitives in JavaScript that do not get wrapped are null and undefined, making the TypeScript values not assignable to {} from the null and undefined types.

Therefore, T extends {} allows T to be anything except for those with null or undefined in its domain:

class Document<T extends {}>{ /**implementation involving T**/ }
new Document<{ a: string }>(); // valid
new Document<string>(); // valid
new Document<null>(); // error
new Document<undefined>(); // error
new Document<string | undefined>(); // error

It is a loose constraint compared to T extends unknown, but it adds some level of restriction as demonstrated.

Link to Playground for Source Code

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

Enhance your Angular application with lazy loading and nested children components using named outlets

Let me start by explaining that the example provided below is a simplified version of my routes that are not functioning properly. I am working on an angular project, specifically a nativescript angular project, and I suspect the issue lies within Angular ...

Maintain hook varieties during implementation of array deconstruction

I have been developing a straightforward hook to export animation helper and element reference. import { gsap } from 'gsap'; import { useRef } from 'react'; export function useTween<R extends gsap.TweenTarget>(vars: gsap.TweenVar ...

Utilizing Typescript for Efficient Autocomplete in React with Google's API

Struggling to align the types between a Google address autocomplete and a React-Bootstrap form, specifically for the ref. class ProfileForm extends React.Component<PropsFromRedux, ProfileFormState> { private myRef = React.createRef<FormContro ...

The [image link] in the NextJS image was loaded in advance using link preload, but it was not utilized within a short time after the window finished loading

While working on my blog website with NextJS, I encountered a warning in the console related to using next/image: The resource http://localhost:3000/_next/image... was preloaded using link preload but not used within a few seconds from the window's lo ...

Tips for Implementing Guard in Angular Applications Without Using Components

My objective is to trigger a method and redirect to component A or B when the link 'auth/login/:tokenKey' is accessed. However, for this specific link, no component is needed, just a method in the typescript file. How can I achieve this? GetTok ...

Issue with ReactJS Typescript: Cannot assign type 'number' to type '0, 8, 16, 24, 32, 40, or undefined'

I am looking to implement a grid from material-ui in react using typescript. You can view the live demo here. I have made adjustments to the example to make it work with typescript. Here is how my demo.jsx file looks like: import { withStyles } from &apo ...

The 'isLoading' property is not found in the type 'UseMutationResult<AxiosResponse<any, any>, Error, void, unknown>'.ts(2339)

I'm currently working on implementing a delete functionality that displays a loading state using the useMutate function from tanstackquery. However, I encountered an issue where the loading state is not shown when I click the delete button, even after ...

There are two modals present on the page, however only one of them is triggered for all actions in Angular 2

I'm encountering an issue with my page where I have set up two confirmation modals - one for resetting a form and another for deleting an item. Strangely, only the reset modal is being triggered for both actions and I can't figure out why. Could ...

A guide to efficiently removing an element in Angular using TypeScript by considering certain properties

I need help removing an element from an array based on any property such as its key, name, or email. HTML <tr *ngFor="let person of persons;" (click)="remove(person.key)"> <td>{{person.key}}</td> <td>{{person.name}}</td> ...

How can I customize the error message for chai expect in my mocha unit test?

I'm working on a mocha test that uses chai's expect function: it("should parse sails out of cache file", async () => { const sailExtractor = new Extractor(); const result = await sailExtractor.extract("test.xml"); try { e ...

How can I incorporate an interface and specify a particular type as the return value in TypeScript?

interface Inter{ str:string } function func(){ let v:Inter={ str:'abc' }; return v; } func()//Is there a way to ensure that the type of value returned from `func` is {str:'abc'} without explicitly declaring it i ...

Merging all Angular 2 project files into a single app.js document

I've scoured the depths of the internet for an answer to this burning question: How can I merge all my Angular 2 code, along with its dependencies, into a single file? Although this query has been posed countless times before, I bring a fresh perspect ...

What steps should I follow to ensure that TypeScript is aware of the specific proptypes I am implementing?

Is there a way to instruct TypeScript on the prop types that a component is receiving? For example, if multiple is set to true, I would like TypeScript to expect that selectValue will be an array of strings. If it's not present, then TypeScript should ...

There was a TypeError encountered when trying to access the property 'Symbol(Symbol.iterator)' of an undefined variable

Whenever a web service request fails, this exception is thrown: TypeError: Cannot read property 'Symbol(Symbol.iterator)' of undefined Specifically, the HTTP GET request returns a 400 Bad Request error. Below is the component involved in this ...

Encountering Error TS2411 when upgrading from Typescript version 1.0.0 to 1.1.0-1

After updating my TypeScript using npm install typescript -g, I have been encountering a recurring error during compilation. Although the compilation is successful, it's becoming tedious. cmd.exe /D /C C:/Users/Vado/AppData/Roaming/npm/tsc.cmd --sour ...

Trouble with CDK Upgrade: unable to locate a similar command to "expect(SynthUtils.toCloudFormation(stack)).toMatchSnapshot())"

I just started using CDK and I'm currently in the process of upgrading the version for my code. However, in the test, the old CDK has the SynthUtils as shown below: expect(SynthUtils.toCloudFormation(stack)).toMatchSnapshot() I've looked in a ...

Error occurs when attempting to access property on type 'unknown' without apparent cause

My current project involves an Angular application where I need to fetch data from a Rest API. There's a service that successfully retrieves the data and a component designed to display this data. However, during compilation of my application, I encou ...

The Console.Log function will not run if it is placed within the RXJS Tap operator

In my current setup, I have the following observables: this.authenticationService.isSignedIn() -> Observable<Boolean> this.user$ -> Observable<UserModel> I am in need of checking a condition based on both these observables, so I attempt ...

Using a class constructor as an argument for a function that requires a specific function type

Let's consider a scenario where we have a function defined as (fooMaker: (_: string) => Foo): void, in which Foo represents a class. Is there a way to directly pass the constructor of Foo to this function without needing to encase it like so: (s: s ...

How can Karma unit tests with Jasmine in a TypeScript Node project accurately measure code coverage, even with external dependencies?

We have a unique situation with the code coverage of our project involving a node dependency. It's important to note that the npm dependency source code is actually part of our project, as we are responsible for its development and publication. Here&a ...