typescriptインターフェイスで静的プロパティを宣言したいだけですか?これについてはどこにも見つかりませんでした。
interface myInterface {
static Name:string;
}
出来ますか?
typescriptインターフェイスで静的プロパティを宣言したいだけですか?これについてはどこにも見つかりませんでした。
interface myInterface {
static Name:string;
}
出来ますか?
回答:
TypeScriptのインターフェイスで静的プロパティを定義することはできません。
Dateの定義に追加しようとするのではなく、オブジェクトを変更したい場合はDate、それをラップするか、単純にリッチな日付クラスを作成して、Date実行しないことを実行できます。
class RichDate {
public static MinValue = new Date();
}
DateはTypeScriptのインターフェイスであるため、extendsキーワードを使用してクラスで拡張することはできません。これは、日付がクラスである場合に適切なソリューションになるため、少し残念です。
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);
extendsキーワードを使用してTSのインターフェースを拡張できます。クラスでインターフェースを拡張することはできません(静的プロパティを追加するために行う必要があります)。
@Duncanの@Bartvdsの回答に従ってください。ここでは、年月が経過した後でも実行可能な方法を提供しています。
Typescript 1.5がリリースされた(@Jun 15 '15)後のこの時点で、便利なインターフェイス
interface MyType {
instanceMethod();
}
interface MyTypeStatic {
new():MyType;
staticMethod();
}
この方法は、デコレータを使用して実装できます。
/* 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 open issue 13462で私のコメントを参照してください。
インターフェースは通常どおり定義できます。
interface MyInterface {
Name:string;
}
しかし、あなたはただすることはできません
class MyClass implements MyInterface {
static Name:string; // typescript won't care about this field
Name:string; // and demand this one instead
}
クラスが静的プロパティのこのインターフェイスに従う必要があることを表現するには、少しトリックが必要です。
var MyClass: MyInterface;
MyClass = class {
static Name:string; // if the class doesn't have that field it won't compile
}
クラスの名前を保持することもできます。TypeScript(2.0)では問題ありません。
var MyClass: MyInterface;
MyClass = class MyClass {
static Name:string; // if the class doesn't have that field it won't compile
}
多くのインターフェースを静的に継承したい場合は、まずそれらを新しいインターフェースにマージする必要があります:
interface NameInterface {
Name:string;
}
interface AddressInterface {
Address:string;
}
interface NameAndAddressInterface extends NameInterface, AddressInterface { }
var MyClass: NameAndAddressInterface;
MyClass = class MyClass {
static Name:string; // if the class doesn't have that static field code won't compile
static Address:string; // if the class doesn't have that static field code won't compile
}
または、マージされたインターフェイスに名前を付けたくない場合は、次のようにできます。
interface NameInterface {
Name:string;
}
interface AddressInterface {
Address:string;
}
var MyClass: NameInterface & AddressInterface;
MyClass = class MyClass {
static Name:string; // if the class doesn't have that static field code won't compile
static Address:string; // if the class doesn't have that static field code won't compile
}
実施例
@staticImplements。
reply(msg: IBotMsg): Promise<IBotReply>
静的プロパティは通常、オブジェクトの(グローバル)コンストラクターに配置されますが、「interface」キーワードはオブジェクトのインスタンスに適用されます。
TypeScriptでクラスを記述している場合、前述の答えはもちろん正しいです。他の場所に既に実装されているオブジェクトを記述している場合、静的プロパティを含むグローバルコンストラクターは次のように宣言できることを他の人が知るのに役立つかもしれません。
declare var myInterface : {
new(): Interface;
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());
上記new()の静的型を指定する@duncanのソリューションは、インターフェイスでも機能します。
interface MyType {
instanceMethod();
}
interface MyTypeStatic {
new():MyType;
staticMethod();
}
implementますか?
MyType(のようにclass Foo implements MyType)実装します。静的インターフェースは、既存のJSコードを説明するときに、定義でのみ実際に役立ちます。
はい、可能です。これが解決策です
export interface Foo {
test(): void;
}
export namespace Foo {
export function statMethod(): void {
console.log(2);
}
}
Fooを使用してクラス定義を代用していますか?Class FooがstatMethod()を実装する場合、名前空間は現在非推奨になっているため、これは少しハックのようです...
waiting more feedbackます。したがって、静的メソッドがインターフェースに追加されるまで待つか、このようにします。
export namespaceは実際にクラスの実装ですか?それは物事を大きく曲げているようです。クラスで他に何が壊れているのでしょうか。
ここで言及されていない別のオプションは、静的インターフェイスを表す型で変数を定義し、それにクラス式を割り当てることです。
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での関連提案/ディスカッション
同じ名前を使用して、インターフェースをネームスペースとマージできます。
interface myInterface { }
namespace myInterface {
Name:string;
}
ただし、このインターフェイスは、プロパティがあることを知っている場合にのみ役立ちますName。実装できません。
私は特定のユースケースでこれを(デコレータなしで)行う方法を見つけました。
静的メンバーをチェックする重要な部分は、メソッドでIObjectClass使用cls: IObjectClass<T>することcreateObjectです。
//------------------------
// 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のインターフェイスでは静的キーワードはサポートされていませんfunction interfaceが、静的メンバーを持つを作成することで実現できます。
次のコードFactoryでは、2つの静的メンバー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();
Kamil Szotのようなソリューションを実装しましたが、望ましくない影響があります。私はこれをコメントとして投稿するのに十分な評判がないので、誰かがその解決策を試みてこれを読んだ場合に備えて、ここに投稿します。
解決策は次のとおりです。
interface MyInterface {
Name: string;
}
const MyClass = class {
static Name: string;
};
ただし、クラス式を使用するMyClassと、型として使用できません。私が次のようなものを書いた場合:
const myInstance: MyClass;
myInstanceがタイプanyであることが判明し、私のエディタに次のエラーが表示されます:
'MyClass' refers to a value, but is being used as a type here. Did you mean 'typeof MyClass'?ts(2749)
クラスの静的な部分のインターフェースで実現したいタイプよりも重要なタイプを失うことになります。
デコレータを使用するValのソリューションは、この落とし穴を回避します。