gpt4 book ai didi

typescript - 返回传递给它的(可能是抽象的)类实例的通用函数的签名

转载 作者:行者123 更新时间:2023-12-05 05:47:45 25 4
gpt4 key购买 nike

基本上,我尝试在以下(大大简化的)代码中键入 getA():

interface Base {
readonly id: string
}

class Foo implements Base {
get id() {return 'a foo'}
get ping() {return 'pong'}
}

abstract class Bee {
abstract get bing(): string
}

class Bar implements Base, Bee {
get id() {return 'a bar'}
get bing() {return 'Crosby'}
}

class Baz implements Base, Bee {
get id() {return 'a bar'}
get bing() {return 'cherry'}
}

function getA(type, name) {
// Some dynamic lookup happens here
if (type === Foo) {
return new Foo()
} else if (type === Bee && name === 'bar') {
return new Bar()
} else if (type === Bee && name === 'baz') {
return new Baz()
} else {
throw new Error('unknown args')
}
}

console.log(getA(Foo, 'foo').ping)
console.log(getA(Bee, 'bar').bing)

这是 doable (虽然笨拙)没有抽象类:

function getA<T extends Base>(type: {new(): T}, name: string): T

但是抽象类没有构造函数(原因很明显),而且我似乎找不到任何其他方式来引用该类型(而不是它的实例)。如果有更好的方法,我也乐于接受可能的重构建议。

最佳答案

您可以使用 abstract constructor type expression它看起来就像一个普通的“具体”构造函数类型表达式*,只是你写的是 abstract new 而不是 new:

interface Foo {
a: string;
}
type FooCtor = new (a: string) => Foo;
type AbstractFooCtor = abstract new (a: string) => Foo;

如果你有一个具体的构造函数,你可以新建它:

declare let ConcreteFoo: FooCtor;
new ConcreteFoo("yes"); // okay

但是你不能用抽象构造函数来做到这一点:

let AbstractFoo: AbstractFooCtor;
new AbstractFoo("no"); // error, cannot create an instance of an abstract class

请注意,抽象构造函数被认为是具体构造函数的适当父类(super class)型,因此您可以使用具体构造函数代替抽象构造函数,但反之则不行:

AbstractFoo = ConcreteFoo; // okay, concrete ctor is a subtype of abstract ctor
ConcreteFoo = AbstractFoo; // error, abstract ctor is not a subtype of concrete ctor

无论如何,这意味着您可以编写 getA() 的调用签名

function getA(type: abstract new () => any, name: string) {/*...*/}
// or whatever arg/ret you want ^^^^^^^^^

一切都应该正常。

Playground link to code

*TS 文档引用 construct signaturesabstract construct signatures而不是构造函数类型表达式,但这有点模棱两可或不正确。调用/构造签名看起来像{ (arg: Arg): Ret } { new (arg: Arg): Ret } 而a函数/构造函数 type expression看起来像 (arg: Arg) => Retnew (arg: Arg) => Ret。这种差异在这里很重要,因为虽然 abstract new (arg: Arg) => Ret 自 TS4.2 以来是有效的 TypeScript 语法,但可能等效于 { abstract new (arg: Arg): Ret } 无效 语法。因此我上面的术语。

关于typescript - 返回传递给它的(可能是抽象的)类实例的通用函数的签名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70920837/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com