我只是想在typescript接口中声明一个静态属性?我没有找到任何关于这方面的资料。
interface myInterface {
static Name:string;
}
这可能吗?
我只是想在typescript接口中声明一个静态属性?我没有找到任何关于这方面的资料。
interface myInterface {
static Name:string;
}
这可能吗?
当前回答
静态修饰符不能出现在类型成员上(TypeScript错误TS1070)。这就是为什么我建议使用抽象类和继承来解决任务:
例子
// Interface definition
abstract class MyInterface {
static MyName: string;
abstract getText(): string;
}
// Interface implementation
class MyClass extends MyInterface {
static MyName = 'TestName';
getText(): string {
return `This is my name static name "${MyClass.MyName}".`;
}
}
// Test run
const test: MyInterface = new MyClass();
console.log(test.getText());
其他回答
这里有一个相当简单的方法:
interface MyClass {
new (): MyClassInstance;
staticMethod(): string;
}
interface MyClassInstance {
instanceMethod(): string;
}
const Class: MyClass = class {
static staticMethod() {
return "This is a static method";
}
instanceMethod() {
return "This is an instance method";
}
}
Class.staticMethod();
// Has type MyClassInstance
const instance = new Class();
instance.instanceMethod();
请注意,这并不允许您像通常那样让类扩展接口,但对于许多情况来说,这已经足够好了。
静态修饰符不能出现在类型成员上(TypeScript错误TS1070)。这就是为什么我建议使用抽象类和继承来解决任务:
例子
// Interface definition
abstract class MyInterface {
static MyName: string;
abstract getText(): string;
}
// Interface implementation
class MyClass extends MyInterface {
static MyName = 'TestName';
getText(): string {
return `This is my name static name "${MyClass.MyName}".`;
}
}
// Test run
const test: MyInterface = new MyClass();
console.log(test.getText());
我为我的特定用例找到了这样做的方法(不需要装饰器)。
检查静态成员的重要部分是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);
虽然静态关键字不支持接口在Typescript 但我们可以通过创建一个具有静态成员的函数接口来实现。
在下面的代码中,我创建了一个函数接口Factory,它有两个静态成员serialNumber和printSerial。
// factory is a function interface
interface Factory<T> {
(name: string, age: number): T;
//staic property
serialNumber: number;
//static method
printSrial: () => void;
}
class Dog {
constructor(public name: string, public age: number) { }
}
const dogFactory: Factory<Dog> = (name, age) => {
return new Dog(name, age);
}
// initialising static members
dogFactory.serialNumber = 1234;
dogFactory.printSrial = () => console.log(dogFactory.serialNumber);
//instance of Dog that DogFactory creates
const myDog = dogFactory("spike", 3);
//static property that returns 1234
console.log(dogFactory.serialNumber)
//static method that prints the serial 1234
dogFactory.printSrial();
温特特拉特给出了一个很好的答案,让我走上了正确的轨道。 然而,强制在静态接口中包含构造函数是非常不方便的。
简化版本
反转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
操场上的链接