Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typing constructor functions in TypeScript

Tags:

typescript

I'm having problems understanding how to correctly type a constructor function in TS. I'm aware that a common answer would be to use a class, but I'm currently exploring TS features. In my tsconfig.json I have noImplicitAny: true.

My constructor function looks like this in JS:

function User(username) {
     this.username = username
}
User.prototype.age = 57

My first attempt to type the functions relied on the TS docs that explain how to define call signatures:

interface IUser {
    username: string;
    age: number;
}

type UserConstructor = {
    (username: string): void;
    new (username: string): IUser;
}

const User: UserConstructor = function(username: string) {
    this.username = username
}
User.prototype.age = 57

The compiler complains since the value of this is unknown and the call signatures don't seem to match.

After doing some research, I was able to come up with a version that works but I don't really like it:

interface ICUser {
    username: string;
    age: number;
}

function ConstructedUser(this:ICUser, username: string) {
    this.username = username;
}

ConstructedUser.prototype.dateOfBirth = "Freb"

Here's what I don't like about solution nr. 2:

  • I'm not sure I completely understand the explicit passing of this since there aren't any official docs on this.
  • The typing is very verbose and does not separate between properties on the instance and prototype chain.

I wasn't able to find good resources on how to type constructor functions and hoped someone might be able to help.

like image 959
Xen_mar Avatar asked Sep 08 '25 07:09

Xen_mar


1 Answers

It looks like the answer is that you can't do this without type assertions (e.g. as any), because you aren't supposed to write constructor functions in Typescript. This GitHub issue suggests allowing it, and the suggestion was marked as "declined" and closed:

If anything we'd rather remove the ability to new void functions. The inconsistency is unfortunate but we didn't want to add a large type safety hole for the sake of consistency with a facet we don't even like in the first place.

The proper way to write your code in Typescript is using the class syntax to declare a class. If it's needed for compatibility with older browsers, you can force tsc to convert your class declaration into a constructor function during compilation, by setting the target language level to ES3 or ES5.

like image 130
kaya3 Avatar answered Sep 10 '25 00:09

kaya3