如何`类型构造函数 = Function&{prototype:T}`适用于TypeScript中的抽象构造函数类型?

问题描述 投票:1回答:1

关于TypeScript中的抽象构造函数类型有这个Q&A,这个问题我想知道答案:

Abstract constructor type in TypeScript

不幸的是,接受的答案不过是一个无法解释的单行:type Constructor<T> = Function & { prototype: T }

似乎这个答案对于提问者来说已经足够好了,这是公认的答案,但我无法理解答案如何适用于这个问题。

我已经尝试在评论中提问了,我试过要求聊天的人解释答案,但无济于事。此外,我认识到这只是一个与此不同的问题,但这仍然是一个关于代码的独特问题。

如何使用某种类型的Function & { prototype: T }来模拟已知构造函数类型的抽象类?

typescript constructor abstract-class
1个回答
4
投票

JavaScript,所有函数都有一个名为prototype的特殊属性。如果你使用一个函数作为构造函数(通过使用new调用它),构造的实例将把它作为它的原型。这是ES2015之前的JavaScript在JavaScript中的工作方式:

// ES5-flavored class 
function Foo() { } // a normal function 
Foo.prototype.prop = 0; // adding a property to Foo.prototype
var f = new Foo(); // using Foo as a constructor
f.prop; // the instance inherits the added property

ES2015引入了class语法,它在引擎盖下的行为方式相同......因此构造函数对象仍然具有prototype属性,构造实例继承该属性。

// ES2015-flavored class
class Foo { } // explicitly a class
Foo.prototype.prop = 0; // adding a property to Foo.prototype
const f = new Foo(); // using Foo as a constructor
f.prop; // the instance inherits the added property

TypeScript通过声明所有函数实现的Function接口具有prototype property of type any来对此进行建模。此外,当使用class语法时,构造函数仍然被视为Function,并且prototypeconstructor属性从any缩小到与构造的类实例相同的类型:

// TypeScript code
class Foo { 
  prop!: number;  // Foo has a prop
} 
Foo.prototype; // inspects as type Foo
Foo.prototype.prop = 0; // so this works
const f = new Foo(); // inspects as type Foo
f.prop; // inspects as type number

甚至TypeScript中的abstract类也有一个prototype属性,其类型与实例类型相同。因此,虽然你不能在抽象类构造函数上调用new,或者将它与new() => any这样的新类型匹配,但你仍然可以谈论它的prototype

// more TS code
abstract class Bar {
  abstract prop: number;
}
Bar.prototype; // inspects as type Bar
Bar.prototype.prop = 0; // so this works
const b = new Bar(); // whoops can't do this though

所有这些意味着在TypeScript中,一个可能抽象的类构造函数是Function的(子类型),其prototype属性是构造函数的实例类型。因此,你可以这么说

type PossiblyAbstractConstructor<T> = Function & {prototype: T};

使用intersection运算符来组合Function和“对象与prototype类型的T属性”...

或类似的

interface PossiblyAbstractConstructor<T> extends Function {
  prototype: T;
}

使用interface extension来达到同样的效果......

你知道以下内容是有效的:

const fooConstructor: PossiblyAbstractConstructor<Foo> = Foo;
const barConstructor: PossiblyAbstractConstructor<Bar> = Bar;

这应该解释原始问题的答案是如何适用的。希望有所帮助。祝好运!

© www.soinside.com 2019 - 2024. All rights reserved.