TypeScript:继承类中静态方法的自引用返回类型
Posted
技术标签:
【中文标题】TypeScript:继承类中静态方法的自引用返回类型【英文标题】:TypeScript: self-referencing return type for static methods in inheriting classes 【发布时间】:2015-12-04 21:47:34 【问题描述】:使用 TypeScript 1.7 中的Polymorphic this,正如我发现的here,我们可以在返回类型为this
的类中定义一个方法,并且自动地,任何扩展该类并继承方法的类将将它们的返回类型设置为各自的this
类型。像这样:
class Model
save():this // return type: Model
// save the current instance and return it
class SomeModel extends Model
// inherits the save() method - return type: SomeModel
但是,我所追求的是继承static
方法,其返回类型引用类本身。最好在代码中描述:
class Model
static getAll():Model[]
// return all recorded instances of Model as an array
save():this
// save the current instance and return it
class SomeModel extends Model
// inherits the save() method - return type: SomeModel
// also inherits getAll() - return type: Model (how can we make that SomeModel?)
也许我必须想出一种不同的方法来实现它,因为 TypeScript 1.7 中的多态 this
不支持 static
方法设计。
编辑:我想我们会看到这个 Github 问题如何结束:https://github.com/Microsoft/TypeScript/issues/5863
【问题讨论】:
【参考方案1】:这在 TypeScript 2.0+ 中是可行的。通过使用内联 new(): T
类型来捕获 this
,您将得到您想要的:
type Constructor<T> = new (): T
class BaseModel
static getAll<T>(this: Constructor<T>): T[]
return [] // dummy impl
/**
* Example of static method with an argument:
*/
static getById<T>(this: Constructor<T>, id: number): T | undefined
return // dummy impl
save(): this
return this // dummy impl
class SubModel extends BaseModel
const sub = new SubModel()
const savedSub: SubModel = sub.save()
// Behold: SubModel.getAll() returns SubModels, not BaseModel
const savedSubs: SubModel[] = SubModel.getAll()
请注意,getAll
仍然不希望这种类型的参数。
有关详细信息,请参阅https://www.typescriptlang.org/docs/handbook/2/generics.html#using-class-types-in-generics 和 https://***.com/a/45262288/1268016
【讨论】:
如果您在getAll
的函数实现中使用其他静态方法,例如this.someOtherStaticMethod()
,则提供者会抱怨。你可以通过(this as any)
来解决这个问题
@Flion 每次你投到any
,你都会让 Hejlsberg 先生哭泣。您可以创建一个BaseModelClass
来捕获静态签名,而不是使用内联的 new(): T
类型。有关工作示例,请参阅 github.com/Vincit/objection.js/blob/master/typings/objection/…。
谢谢,我同意,最好尽可能让 Hejlsberg 先生高兴 :) .. BaseModelClass 在大多数情况下工作得更整洁。但我仍然对getAll
中的this.someOtherPrivateStaticMethod()
有疑问。接口不允许私有声明,但我需要在接口中定义它。如果我将它定义为 public,当我在一个子类上调用 getAll
时,编译器会抱怨它在一个子类中是私有的,但在另一个子类中没有
如何在不强制转换的情况下使用其他静态方法?我有一个基类,但我不想为我的基类创建一个大接口......当我尝试使用 this.otherStatic 时,它会抱怨。如果我使用 (基于simplest answer 到GitHub issue,您可以像这样使用InstanceType<>
:
class Foo
static create<T extends typeof Foo>(this: T): InstanceType<T>
return new this() as InstanceType<T>
static getAll<T extends typeof Foo>(this: T): Array<InstanceType<T>>
return []
class Bar extends Foo
const a = Bar.getAll() // typeof a is Bar[]
const b = Bar.create() // typeof b is Bar.
我在链接的 GitHub 示例中放入 create
函数只是为了说明。
【讨论】:
哇,我一直在寻找这个答案很长一段时间。谢谢! 静态 getter 的解决方案是什么,因为它不能带参数? 这应该是公认的答案。谢谢 这是对的。谢谢你。我同意,这应该是公认的答案。【参考方案3】:基于Brains answer,您可以直接使用返回类型
(typeof Class)['foo']
示例:
export class MyClass
myFunction(param:string):number
return typeof param === "string"?1:0
/** Just class['foo'] to normal methods */
static myStaticFunctions(cards: string): Parameters<MyClass['MyFunction']>[0]
/** and *(typeof class)* ['foo'] to static methods */
const typedReturn: ReturnType<(typeof MyClass)['myStaticFunctions']> = "works"
return typedReturn
【讨论】:
【参考方案4】:你期望这个静态方法在继承的子类中返回什么?是不是这样的:
class A
private static _instances = new Array<A>();
static instances(): A[] return A._instances;
constructor() A._instances.push(this);
class B extends A
static instances(): B[]
return <B[]>(A.instances().filter(i => i instanceof B));
constructor() super(); ;
var a = new A();
var b = new B();
console.log(
"A count: " + A.instances().length +
" B count: " + B.instances().length);
这将输出“A 计数:2 B 计数:1”。或者你期待什么?
【讨论】:
他希望他的getAll()
方法返回子类型的数组,而不必重新定义子类中的方法。见***.com/a/42768627/1268016以上是关于TypeScript:继承类中静态方法的自引用返回类型的主要内容,如果未能解决你的问题,请参考以下文章