如何使用构造函数/new关键字编写打字稿?

发布于 2025-01-11 00:22:03 字数 1055 浏览 2 评论 0原文

这是来自 MDN 文档 的示例new 关键字的用法

function Car(make, model, year) {
  this.make = make;
  this.model = model;
  this.year = year;
}

const car1 = new Car('Eagle', 'Talon TSi', 1993);

我相信,该函数的 TS 版本将是:

/* car type */
type CarDetails = {
    make: string;
    model: string;
    year: number;
}

/* setting this to type CarDetails */
function Car(this:CarDetails, make: string, model:string, year:number) {
  this.make = make;
  this.model = model;
  this.year = year;
}

这在编写方法时为我提供了智能感知/自动完成功能,但如何使 TS 推断类型创建一个带有 new 关键字的实例。即使在对方法进行打字之后,创建一个如下所示的实例:

const car1 = new Car('Eagle', 'Talon TSi', 1993);

仍然保持car1any类型

如何制作car1的类型推断为 Car 方法的 this 类型?

(没有显式设置实例对象的类型, const car1: CarDetails = new Car(...;

This is an example from MDN docs for the usage of new keyword

function Car(make, model, year) {
  this.make = make;
  this.model = model;
  this.year = year;
}

const car1 = new Car('Eagle', 'Talon TSi', 1993);

I believe, the TS version of the function would be:

/* car type */
type CarDetails = {
    make: string;
    model: string;
    year: number;
}

/* setting this to type CarDetails */
function Car(this:CarDetails, make: string, model:string, year:number) {
  this.make = make;
  this.model = model;
  this.year = year;
}

This gives me intellisense/autocomplete while writing the method but how do I make TS infer types while creating an instance with new keyword. Even after typescripting the method, creating an instance like this:

const car1 = new Car('Eagle', 'Talon TSi', 1993);

still keeps car1 as type any

How to make car1's type infer to be Car method's this type ?

(without explicitly setting type for the instance object, const car1: CarDetails = new Car(...; )

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

三五鸿雁 2025-01-18 00:22:03

显然,类语法应该是可行的方法,但正如你一样,我也在兜圈子,试图找到输出旧的有效 JS 语法的正确解决方案。这是我在这个随机答案中找到的一个很好的近似值,并且在 官方 Typescript 文档。以下是我修改后使其变得更好的相关部分:


// Only instance members here.
export interface Circle { // Name the interface with the same than the var.
  radius: number;
  area: () => number;
  perimeter: () => number;
}

// You could define static members here.
interface CircleConstructor {
  new(radius: number): Circle;
}

export const Circle = function(this: Circle, radius: number) {
  const pi = 3.14;
  this.radius = radius;
  this.area = function () {
    return pi * radius * radius
  }
  this.perimeter = function () {
    return 2 * pi * radius;
  }
} as unknown /*as any*/ as CircleConstructor; // Note the trust-me casting
    
const c = new Circle(3); // okay

这存在一些问题。例如,它使用禁止any类型,或者必须使用as操作符,这是非常丑陋的。作为改进,我使用了 unknown 而不是 any,但核心问题仍然存在。这使得 lint 工具不会抱怨,因此它比 any 有了很大的改进。

这是迄今为止我找到的最好的解决方案。 Typescript 开发人员意识到了这一点,但他们决定不提供对这种“语法”的支持。

Obviously the class syntax should be the way to go, but as you I'm also running in circles trying to find the right solution that outputs the old valid JS syntax. This is a good approximation that I've found in this random answer and it's poorly explained in the official Typescript documentation. Here is the relevant part that I've modified to make it better:


// Only instance members here.
export interface Circle { // Name the interface with the same than the var.
  radius: number;
  area: () => number;
  perimeter: () => number;
}

// You could define static members here.
interface CircleConstructor {
  new(radius: number): Circle;
}

export const Circle = function(this: Circle, radius: number) {
  const pi = 3.14;
  this.radius = radius;
  this.area = function () {
    return pi * radius * radius
  }
  this.perimeter = function () {
    return 2 * pi * radius;
  }
} as unknown /*as any*/ as CircleConstructor; // Note the trust-me casting
    
const c = new Circle(3); // okay

This comes with some issues. For instance, the fact that it's using any type which is forbidden or the necessary use of the as operator which is mega-ugly. As improvement, I've used unknown instead of any but the core problem remains. This makes the lint tool to not complain, so it's a big improvement over the any.

This is the best solution I've found so far. Typescript devs are aware of this, but they have decided to not provide support for this kind of "syntax".

ぽ尐不点ル 2025-01-18 00:22:03

您可以使用类来代替:

class Car {

  make: string;
  model: string;
  year: number;
  
  constructor(make: string, model: string, year: number) {
    this.make = make;
    this.model = model;
    this.year = year;
  }
}

// usage is the same

const car1 = new Car('Eagle', 'Talon TSi', 1993);

You could use classes instead:

class Car {

  make: string;
  model: string;
  year: number;
  
  constructor(make: string, model: string, year: number) {
    this.make = make;
    this.model = model;
    this.year = year;
  }
}

// usage is the same

const car1 = new Car('Eagle', 'Talon TSi', 1993);

指尖上得阳光 2025-01-18 00:22:03

最近不得不对两种方式提供支持,最终得到了这样的结果

export declare class Maybe<Value> {
  constructor(status: "resolved" | "rejected", state: Value | unknown);
}
export function Maybe<Value>(this: Maybe<unknown> | undefined, status: "resolved" | "rejected", state: Value | unknown): Maybe<Value> {
  const instance = this ?? Object.create(Maybe.prototype);
  return instance;
}

Recently had to make support for both ways and ended up with something like this

export declare class Maybe<Value> {
  constructor(status: "resolved" | "rejected", state: Value | unknown);
}
export function Maybe<Value>(this: Maybe<unknown> | undefined, status: "resolved" | "rejected", state: Value | unknown): Maybe<Value> {
  const instance = this ?? Object.create(Maybe.prototype);
  return instance;
}

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文