我只是想在typescript接口中声明一个静态属性?我没有找到任何关于这方面的资料。
interface myInterface {
static Name:string;
}
这可能吗?
我只是想在typescript接口中声明一个静态属性?我没有找到任何关于这方面的资料。
interface myInterface {
static Name:string;
}
这可能吗?
当前回答
这里没有提到的另一个选项是用表示静态接口的类型定义变量,并为其分配类表达式:
interface MyType {
instanceMethod(): void;
}
interface MyTypeStatic {
new(): MyType;
staticMethod(): void;
}
// ok
const MyTypeClass: MyTypeStatic = class MyTypeClass {
public static staticMethod() { }
instanceMethod() { }
}
// error: 'instanceMethod' is missing
const MyTypeClass1: MyTypeStatic = class MyTypeClass {
public static staticMethod() { }
}
// error: 'staticMethod' is missing
const MyTypeClass2: MyTypeStatic = class MyTypeClass {
instanceMethod() { }
}
效果与使用装饰器的应答相同,但没有装饰器的开销
操场上
GitHub上的相关建议/讨论
其他回答
遵循@Duncan的@Bartvds的回答,在这里提供了一个可行的方法。
在Typescript 1.5发布后(@Jun 15 '15),你的有用界面
interface MyType {
instanceMethod();
}
interface MyTypeStatic {
new():MyType;
staticMethod();
}
可以在decorator的帮助下以这种方式实现。
/* class decorator */
function staticImplements<T>() {
return <U extends T>(constructor: U) => {constructor};
}
@staticImplements<MyTypeStatic>() /* this statement implements both normal interface & static interface */
class MyTypeClass { /* implements MyType { */ /* so this become optional not required */
public static staticMethod() {}
instanceMethod() {}
}
参考我在github issue 13462的评论。
视觉效果: 编译错误,提示缺少静态方法。
静态方法实现后,提示方法缺失。
在静态接口和正常接口完成后进行编译。
在TypeScript中,你不能在接口上定义静态属性。
假设您想要更改Date对象,而不是尝试添加到Date的定义中,您可以包装它,或者简单地创建富Date类来完成Date没有完成的工作。
class RichDate {
public static MinValue = new Date();
}
因为Date是TypeScript中的一个接口,你不能使用extends关键字将它扩展为一个类,这有点遗憾,因为如果Date是一个类,这将是一个很好的解决方案。
如果你想扩展Date对象以在原型上提供MinValue属性,你可以:
interface Date {
MinValue: Date;
}
Date.prototype.MinValue = new Date(0);
使用:
var x = new Date();
console.log(x.MinValue);
如果你想让它在没有实例的情况下可用,你也可以…但这有点繁琐。
interface DateStatic extends Date {
MinValue: Date;
}
Date['MinValue'] = new Date(0);
使用:
var x: DateStatic = <any>Date; // We aren't using an instance
console.log(x.MinValue);
静态属性通常放在对象的(全局)构造函数上,而“interface”关键字适用于对象的实例。
如果你用TypeScript编写类,前面给出的答案当然是正确的。如果你描述的是一个已经在其他地方实现的对象,那么包含静态属性的全局构造函数可以这样声明:
declare var myInterface : {
new(): Interface;
Name:string;
}
我为我的特定用例找到了这样做的方法(不需要装饰器)。
检查静态成员的重要部分是IObjectClass,并在createObject方法中使用cls: IObjectClass<T>:
//------------------------
// Library
//------------------------
interface IObject {
id: number;
}
interface IObjectClass<T> {
new(): T;
table_name: string;
}
function createObject<T extends IObject>(cls: IObjectClass<T>, data:Partial<T>):T {
let obj:T = (<any>Object).assign({},
data,
{
id: 1,
table_name: cls.table_name,
}
)
return obj;
}
//------------------------
// Implementation
//------------------------
export class User implements IObject {
static table_name: string = 'user';
id: number;
name: string;
}
//------------------------
// Application
//------------------------
let user = createObject(User, {name: 'Jimmy'});
console.log(user.name);
温特特拉特给出了一个很好的答案,让我走上了正确的轨道。 然而,强制在静态接口中包含构造函数是非常不方便的。
简化版本
反转extends函数得到:
type Static<TClass extends IStaticInterface & { new(...args) }, IStaticInterface>
= InstanceType<TClass>;
不需要为接口添加构造函数:
interface IMeow { readonly IsMeow: boolean; }
并像这样方便地使用:
class Cat implements Static<typeof Cat, IMeow> {
readonly static IsMeow = true;
}
就像之前一样,如果Cat中缺少静态的IsMeow,它会给出一个非常明确的错误。 也像以前一样,它在其他方面仍然正常工作。
奇特的可读性(主观)
在类型后面需要一个"implements"字符串:
type Static<TClass extends IStaticInterface & { new(...args) },
_txt extends "implements", IStaticInterface>
= InstanceType<TClass>;
这里再次演示我们的猫:
class Cat implements Static<typeof Cat, "implements", IMeow> {
static readonly IsMeow = true;
}
合并多个(过多)
这真的不需要,你只需要重复Static<…>,但下面是:
type Static<TClass extends InterfacesCombined & { new(...args) }, _txt extends "implements",
IStaticInterface, IStatic2 = {}, IStatic3 = {}, IStatic4 = {}, IStatic5 = {},
InterfacesCombined extends IStaticInterface & IStatic2 & IStatic3 & IStatic4 & IStatic5
= IStaticInterface & IStatic2 & IStatic3 & IStatic4 & IStatic5>
= InstanceType<TClass>;
为了演示让我们升级我们的猫更复杂:
interface IPurr { purr(): string; }
interface ILick { Lick(human: any): void; }
用法如下:
class Cat implements IPurr, Static<typeof Cat, "implements", IMeow, ILick> {
static readonly IsMeow = true;
static Lick(human: any) { /* obey me homan! */ }
purr() { return "Prrrrr"; }
}
一个具体的静态接口
如果你经常使用静态接口,你不会想要键入所有的静态<…的东西。 首先让我们先把这个小帮手弄走:
type New<T> = { new(...args: any): T };
现在让我们“烘焙”一个静态的ILick接口:
type IStaticLick<TClass extends ILick & New<InstanceType<TClass>> = InstanceType<TClass>;
瞧:
class Cat2 implements IStaticLick<typeof Cat2> {
static Lick(human: any) { /* obey me homan! */ }
}
到底发生了什么?
我们只是要求typeof T实现一些东西,使其成为“静态接口”的有效参数。
所以如果接口IFoo {stuff} +类Foo实现IFoo说Foo是“stuff”,那么我们所说的是“stuff”必须在T中,因为T被允许在Static<T中,…>。
所以类Foo的implements部分实现了Static<…>并没有真正说明Foo有什么特殊的东西。更确切地说,我们只是说我们有这些花哨的<括号>,里面是一个只接受“东西”滚轮的VIP俱乐部!
换句话说,我们可以写成:
class FakeCat implements IStaticLick<typeof Cat2> { }
...明白我的意思了吧?
我们试图通过要求静态<TClass,…来减少这个明显的问题。>实际实现TClass的实例类型。但是,如果InstanceType<TClass>没有任何实例成员(例如我们的Cat2类),则此方法将不起任何作用。
FakeCat确实实现了Cat2 -因为它不是很难实现:{}。
Demo
操场上的链接