我只是想在typescript接口中声明一个静态属性?我没有找到任何关于这方面的资料。
interface myInterface {
static Name:string;
}
这可能吗?
我只是想在typescript接口中声明一个静态属性?我没有找到任何关于这方面的资料。
interface myInterface {
static Name:string;
}
这可能吗?
当前回答
是的,这是可能的。这是解决方案
export interface Foo {
test(): void;
}
export namespace Foo {
export function statMethod(): void {
console.log(2);
}
}
其他回答
这里有一个相当简单的方法:
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();
请注意,这并不允许您像通常那样让类扩展接口,但对于许多情况来说,这已经足够好了。
是的,这是可能的。这是解决方案
export interface Foo {
test(): void;
}
export namespace Foo {
export function statMethod(): void {
console.log(2);
}
}
我有点惊讶于上面的答案是多么的复杂!但也许这只是因为这个帖子太老了。
编辑:实际上,在经过一些测试后,我最初的尝试被证明是无用的,而且这个问题比我最初预期的要更难解决。
After about an hour or so of tinkering however, I think I may have just found the best/cleanest solution so far (building upon my initial idea)! If the question posed is "How do I include static properties in an interface?", then I think this is a fairly decent answer. This is at least better than extending a class if all you need is an interface (compiletime typing/requirements/restraints). There's no real drawback (well, maybe one small one) to this either since the solution is 100% ambient (unlike extends-based class extension like some answers are suggesting) and classes are constants regardless (immutable references that are not hoisted when using the standard class declaration syntax instead of a class expression as I'm doing here). This incurs no runtime overhead and doesn't require runtime class inheritance. You can define the entire class (both static and non-static members) all in one (ambient class used as an) interface!
以下是如何做到这一点!
/** ./interface.ts */
// In a file module (best), or wrap in ts module or namespace block
// Putting this in a module provides encapsulation ensuring that no one is
// at risk of misusing this class (it must be used as a type only).
// Export only a type reference which will make it error is someone tries
// to use it as a value (such as in an `extends` clause, or trying to
// instantiate it).
/**
* Other Ideas For Names To Differentiate From Actual Classes/Non-Ambient Values:
* MyClassInterface or _Interface_MyClass or MyClass_Interface or Interface_MyClass
**/
declare class _MyClassInterface {
static staticProp: string;
static staticMethod(): number;
readonly prop: boolean
/**
* Note: Above, readonly won't need to be specified in the real class
* but the prop *will* still be readonly anyway.
*
* Now for the only caveat!
* It does appear however that you cannot mark anything private or
* protected in this pseudo-interface which is a bummer, only props
* and methods that appear only in the real class can be.
*/
prop2: boolean;
method(): Function;
constructor(p1: string, p2: number);
}
export type MyClassInterface = typeof _MyClassInterface;
现在使用接口
/** ./consumer.ts */
import { MyClassInterface } from "./interface" // type import
const MyClass: MyClassInterface = class {
static staticProp: string;
prop: boolean;
prop2: boolean;
protected onlyOnRealClass: boolean; /* this is ok since this prop doesn't exist on the interface */
static staticMethod() {
return 5;
}
method() {
return () => {};
}
constructor(p1: string, p2: number) {}
};
注意,typeof关键字在这里是绝对必要的(如果我没记错的话,这是因为如果没有它,typescript会认为我们在指定实例类型,而我们真正想要的是类本身的类型)。比如当我们这样做的时候
const a: MyClass = new MyClass()
没有typeof关键字,我们说a应该是MyClass的一个实例,而不是MyClass本身。
抽象确保你不会意外地尝试实例化类…
Edit: Actually I'm removing the abstract keyword from my answer because it turns out that the real class actually inherits the property of being abstract from the ambient class (makes sense), and will therefore not instantiate w/o the compiler complaining if the ambient class that provides its type is marked abstract... just gonna have to deal with ts not erroring if the ambient class is ever accidentally instantiated. It might be a decent idea then to prefix the ambient class declaration/name with an underscore and/or include the word Interface in the name so its proper use is clear (edit: I have since tackled this issue by encapsulating the interface in a file module thereby rendering it private to all other code and then exporting only a type reference to it).
这就是它的全部!
将接口放入模块中并不是完全必要的,但它提供了一些小好处,包括:
在整个实现代码中使用的“公开的”广泛使用的类型注释变得稍微小了一些,因为它不再包含关键字typeof 与包装的环境类/接口声明不同,导出/向外标识符严格来说是一种类型(别名),因此如果有人试图实例化它或在extends子句中使用它(或在其他需要运行时值的地方使用它),就会发生错误。
I'm not supplying a class name for the Class Expression in this example because Class Expressions, like all Function Expressions, will just inherit the identifier that they are assigned to if a class name if not provided. So if your identifier is identical to the name you want for that class or function anyways, you can just leave it off. Or, you may provide one inline as usual and it will take precedence over the identifier. A class or function name can also be changed after function/class creation, but only via Object.defineProperty or Object.defineProperties.
FWIW类实际上可以由另一个类实现(至少在TS的最新版本中),但静态属性将被忽略。似乎实现任何东西都只适用于原型的两个方向(到/从)。
简单的例子
interface Person {
name: string;
age: number;
}
abstract class Trackable {
static TrackInstances: number;
}
class Pablo extends Trackable implements Person {
constructor(public name: string, public age: number) { Pablo.TrackInstances+=1; }
}
console.log(Pablo.TrackInstances);
遵循@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的评论。
视觉效果: 编译错误,提示缺少静态方法。
静态方法实现后,提示方法缺失。
在静态接口和正常接口完成后进行编译。