我只是想在typescript接口中声明一个静态属性?我没有找到任何关于这方面的资料。
interface myInterface {
static Name:string;
}
这可能吗?
我只是想在typescript接口中声明一个静态属性?我没有找到任何关于这方面的资料。
interface myInterface {
static Name:string;
}
这可能吗?
当前回答
温特特拉特给出了一个很好的答案,让我走上了正确的轨道。 然而,强制在静态接口中包含构造函数是非常不方便的。
简化版本
反转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
操场上的链接
其他回答
是的,这是可能的。这是解决方案
export interface Foo {
test(): void;
}
export namespace Foo {
export function statMethod(): void {
console.log(2);
}
}
可以使用相同的名称将接口和命名空间合并:
interface myInterface { }
namespace myInterface {
Name:string;
}
但是这个接口只有知道它的属性Name才有用。你不能实现它。
我的解决方案对于添加额外静态构造函数的用例非常有效。我已经测试过了,它通过了所有的测试。如果有人发现有问题,请告诉我。
我做了一个泛型类型,它接受接口和静态接口。
它适用于具体类和抽象类。
我使用条件类型来设计它,这样所有的错误都可以传播 到实现接口的类,而不是接口本身。
注意:错误传播允许vscode快速修复(实现所有方法)。唯一的缺点是你必须自己应用static关键字,因为没有快速修复这个错误的方法。
的接口:
type Class<T = any> = new (...args: any[]) => T;
type AbstractClass<T = any> = abstract new (...args: any[]) => T;
type Interface<C extends Class<InstanceType<C>> | AbstractClass<InstanceType<C>>, SI, I = {}> =
C extends Class<InstanceType<C>>
// ConcreteClass
? InstanceType<C> extends I
? C extends (SI & Class<InstanceType<C>>)
? (InstanceType<C> & I)
: (SI & Class<InstanceType<C>>) // Indicate StaticInterface Error
: I // Indicate Interface Error
// AbstractClass
: InstanceType<C> extends I
? C extends (SI & AbstractClass<InstanceType<C>>)
? (InstanceType<C> & I)
: (SI & AbstractClass<InstanceType<C>>) // Indicate StaticInterface Error
: I // Indicate Interface Error
用法:
interface MyInterface {
instanceMethod(): number;
}
interface MyStaticInterface {
staticMethod(): number;
}
class MyClass implements Interface<typeof MyClass, MyStaticInterface, MyInterface> {
static staticMethod(): number {
return 50;
}
instanceMethod(): number {
return 100;
}
static otherStatic() {
return "HELLO"
}
otherInstance() {
return "GOODBYE"
}
}
abstract class MyClass1 implements Interface<typeof MyClass1, MyStaticInterface, MyInterface> {
static staticMethod(): number {
return 50;
}
instanceMethod(): number {
return 20;
}
static otherStatic() {
return "HELLO"
}
otherInstance() {
return "GOODBYE"
}
abstract abstractMethod() : number;
}
温特特拉特给出了一个很好的答案,让我走上了正确的轨道。 然而,强制在静态接口中包含构造函数是非常不方便的。
简化版本
反转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
操场上的链接
静态修饰符不能出现在类型成员上(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());