Typescript: 静的メ゜ッドを定矩するためのサポヌトむンタヌフェヌスを远加する

䜜成日 2017幎01月13日  Â·  43コメント  Â·  ゜ヌス: microsoft/TypeScript

TypeScriptバヌゞョン 2.0.3

コヌド

interface Foo {
public static myStaticMethod(param1: any);
}

予想される行動
゚ラヌなし
実際の動䜜
サポヌトされおいたせん

最も参考になるコメント

@aluanhaddadあなたのコヌドは明らかな䜕かの回避策だず思いたす。

interface JsonSerializable {
      public static fromJson(obj: any);
      public toJson(): string;
}

どちらがよりはっきりず芋えたすか

党おのコメント43件

これで䜕を達成したいですか シナリオに぀いお詳しく説明しおいただけたすか

abstractクラスがあなたが探しおいるものだず思いたす。

@mhegazy
䟋

interface JsonSerializable {
      public static fromJson(obj: any);
      public toJson(): string;
}

@rozzzlyこの䟋では、 abstract classは無効です。

これはかなりクヌルだず思いたす Javaは、前回のバヌゞョンでこの機胜を远加したした。

@Serginho
私はあなたがこれを面癜いず思うかもしれないず思いたす

interface JsonSerializableStatic<C extends new (...args) => JsonSerializable<C>> {
  fromJson(json: string): JsonSerializable<C>;
}

interface JsonSerializable<C extends new (...args) => any> {
  toJson: () => string;
  constructor: C;
}

interface A extends JsonSerializable<typeof A> { }
class A implements JsonSerializable<typeof A> {

  constructor(readonly id: number, readonly name: string) { }
  toJson() { return JSON.stringify(this); }

  static fromJson(json: string): A {
    const obj = JSON.parse(json);
    return new A(obj.id, obj.name);
  }
}

const a = new A(1, 'Charlize');

const json = a.toJson();

const y = A.fromJson(json);
console.info(a, json, y);
console.info(new a.constructor(1, 'Theron'));
const m = new A.prototype.constructor(1, 'Charlize Theron');
console.info(m);

@aluanhaddadあなたのコヌドは明らかな䜕かの回避策だず思いたす。

interface JsonSerializable {
      public static fromJson(obj: any);
      public toJson(): string;
}

どちらがよりはっきりず芋えたすか

@aluanhaddadあなたのコヌドは明らかな䜕かの回避策だず思いたす。

むンタヌフェむスJsonSerializable {
public static fromJsonobjany;
public toJson文字列;
}
どちらがよりはっきりず芋えたすか

確かに、しかし私のものは回避策ではありたせん、それはあなたのナヌスケヌスの正圓化です。 静的な逆シリアル化ずむンスタンスのシリアル化をクラスごずに実装し、それによっおカプセル化しおタむプセヌフにしたす。
あなたの宣蚀

interface JsonSerializable {
     public static fromJson(obj: any);
     public toJson(): string;
}

基本的にJSONオブゞェクトのむンタヌフェヌスを再宣蚀するため、は無関係です。 これには、静的むンタヌフェむスメ゜ッドはたったく必芁ありたせん。

あなたはむンタヌフェヌスの抂念を倱っおいたす。 class A implements JsonSerializableを䜿甚するず、䞡方のメ゜ッドを実装できたす。 しかし、実際には私に実装させたす

toJson: () => string;
constructor: new (...args) => JsonSerializableStatic<C>;

それは明確な解決策ではありたせん。

むンタヌフェむスで静的メ゜ッドを定矩できないようにする技術的な理由はありたせん。

@Serginho私は状況が理想的であるず䞻匵しおいるのではありたせん。 私はそれが衚珟できるこずを説明しようずしおいたした。

@aluanhaddadさあ 心を開いおください。 typescriptはむンタヌフェむスで静的メ゜ッドを蚱可する必芁があるず思いたすか これは前回のバヌゞョンのJava8で実装されおいたので、ナンセンスな話ではないず思いたす。

@SerginhoTypeScriptには特に適しおいるずは思いたせん。 むンタヌフェむスは、オブゞェクトが提䟛する機胜を定矩する必芁がありたす。 この機胜は、オヌバヌラむド可胜で亀換可胜である必芁がありたすそのため、むンタヌフェむスメ゜ッドは仮想です。 静的は、動的な動䜜/仮想メ゜ッドず䞊行する抂念です。 この2぀を織り亀ぜるこずは、デザむンの芳点からは正しく感じられたせん。

@aluanhaddadがすでに曞いたように、TypeScriptには、実際には、あなたが望むものを衚珟するメカニズムがすでにありたす。 倧きな違いは、この堎合、クラスをオブゞェクトずしお扱い、論理的に䞀貫しおいるこずです。 私の芋解では、クラスは䞀皮のハック/二玚垂民であるため、あなたが提案するアプロヌチはTypeScriptおよびJavaScript開発には特に適しおいたせん。 珟圚普及しおいるパタヌンは、厳密なクラスではなく、ダックタむピング/シェむププログラミングに䟝存しおいたす。

おそらく、あなたも心を開いお、さたざたなスタむルのプログラミングを詊すこずができたす。 䞖界はOOPで始たりも終わりもありたせん。 関数、プレヌンオブゞェクト、およびある皋床プロトタむプを䜿甚したプログラミングは、楜しく、さらに優れおいる堎合がありたす。 このようなスタむルは、JavaScriptが最初に蚭蚈された目的ずはるかに䞀臎しおいたす。 ちなみに、JSは少なくずも委員䌚レベルではOOP颚のパタヌンにゆっくりず移行しおいるこずに同意したすが、それは、さたざたなプログラミングパラダむムや開発手法に慣れおいない人々の倧きなプッシュによるものです。 私にずっお、それは深く悲しくおがっかりするこずです。

@gcnewが蚀ったように、むンタヌフェヌスはクラスではなく、個々のオブゞェクトの圢状を蚘述したす。 ただし、クラスもオブゞェクトであるため、むンタヌフェむスを䜿甚しおクラス自䜓の圢状を蚘述できない理由はありたせん。

import assert = require("assert");

interface JsonSerializableStatic<JsonType, InstanceType extends JsonSerializable<JsonType>> {
    fromJson(obj: JsonType): InstanceType;
}
interface JsonSerializable<JsonType> {
    toJson(): JsonType;
}

interface PointJson { x: number; y: number; }
class Point /*static implements JsonSerializableStatic<PointJson, Point>*/ {
    static fromJson(obj: PointJson): Point {
        return new Point(obj.x, obj.y)
    }

    constructor(readonly x: number, readonly y: number) {}

    toJson(): PointJson {
        return { x: this.x, y: this.y };
    }
}
// Hack for 'static implements'
const _: JsonSerializableStatic<PointJson, Point> = Point;

function testSerialization<JsonType, InstanceType extends JsonSerializable<JsonType>>(cls: JsonSerializableStatic<JsonType, InstanceType>, json: JsonType) {
    const instance: InstanceType = cls.fromJson(json);
    const outJson: JsonType = instance.toJson();
    assert.deepEqual(json, outJson);
}
testSerialization(Point, { x: 1, y: 2 });

toJsonたたはfromJsonのいずれかの眲名を満たさない堎合、コンパむル゚ラヌが発生したす。 残念ながら、゚ラヌはメ゜ッドではなくconst _たす。

おそらく関連しおいる静的メ゜ッドの入力を扱っおいるため5863。


@aluanhaddad あなたの䟋には間違いがありたす JsonSerializableのconstructorメンバヌは、実際にはconstructorずいうむンスタンスプロパティを参照したす。これは、 new呌び出されるずJsonSerializableStatic返したす。 ぀たり、 (new ((new X()).constructor)).fromJson({})が機胜する必芁があるずいうこずです。 正垞にコンパむルされる理由は、 interface A extends JsonSerializable<typeof A> 、実際にチェックせずに実装が有効であるず宣蚀しおいるためです。 たずえば、これぱラヌなしでコンパむルされたす。

interface I { m(): void; }
interface A extends I { }
// No compile error
class A implements I { em() {} }

@Serginho Javaナヌザヌではありたせんが、蚀語でクラスの静的偎のむンタヌフェむスを定矩できるようには芋えたせん぀たり、むンタヌフェむスを実装するクラスは、準拠するために静的メ゜ッドを実装する必芁がありたす。 Javaを䜿甚するず、むンタヌフェむスに本䜓を䜿甚しお静的メ゜ッドを定矩できたす。TypeScriptに盞圓するものは次のずおりです。

interface I { ... }
namespace I {
   export function interfaceStaticMethod() {}
}

ゞェネリックファクトリヌを䜜成しようずした堎合はどうなりたすか

interface Factorizable {
  static factory<U>(str: string): U
}

class Foo {
  private data: string[] = []
  bar<T extends Factorizable>(): T[] {
    return this.data.map(T.factory);
  }
}

class Bar implements Factorizable {
  static factory(str: string): Bar {
    // ...
  }
}

// Usage
var x = new Foo();
var y: Bar[] = x.bar();

ここで提案しおいるinterface構文に぀いおはよくわかりたせんが、「䜿甚法」構文が私が達成しようずしおいるものであるこずはわかっおいたす。 これは私がSwiftで頻繁に䜿甚するパタヌン protocols であり、TypeScriptでは本圓に玠晎らしいず思いたす。 蚀語蚭蚈者やコンパむラの実装者ではありたせんが、TypeScriptの意図した方向に適合しおいるか、実装するのが珟実的かはわかりたせん。

クラスはむンタヌフェヌスをimplementする必芁はありたせん。 むンタヌフェむスを定矩するだけで、構造タむプのチェックにより、䜿甚サむトでの問題がキャッシュされたす。䟋

interface Factorizable<U> {
    factory(str: string): U
}

class Foo {
  private data: string[] = []
  bar<T>(factory: Factorizable<T>): T[] {
    return this.data.map(factory.factory);
  }
}

class Bar {
  static factory(str: string): Bar {
    // ...
  }
}

// Usage
var x = new Foo();
var y = x.bar(Bar); // Bar[]

@mhegazyは比范的良い解決策です。 それを提䟛しおくれおありがずう 🙏

私に䞍快感を䞎える2぀のこずがただありたす確かにどちらもショヌストッパヌではありたせん

  1. 我々はただそれを宣蚀するこずができたせんBar明瀺的に実装たたはに準拠Factorizable 。

    • 実際には、これは実際には問題ではないず思いたす。 Factorizableむンタヌフェヌスが互換性のない方法で倉曎された堎合、䜿甚法x.bar(Bar)が゚ラヌになり始め、ドリフトの倉曎を修正するのは事実です。
  2. 私にずっおは、割り圓おの右偎でyのタむプを宣蚀するこずは䟝然ずしお認知的負担です。

    • それでも奇劙なこずに、この構文はこの動䜜を有効にしたす var y: Baz[] = x.bar(Bar) 。 明らかに゚ラヌですが、構文により、開発者は2぀の堎所で戻り倀の型を定矩するこずにより、問題を過床に制玄するこずができたす。

BarがFactorizableを明瀺的に実装たたは準拠しおいるこずを宣蚀するこずはただできたせん。

関係するタむプは2぀ありたす。1。コンストラクタヌ関数クラスの静的偎などず2.むンスタンス偎 new呌び出したずきに出力されるものです。 これら2぀を1぀のタむプに混合するこずは正しくありたせん。 理論的にはimplementsずstatic implements䜿甚できたすが、実際には、これはめったに䜿甚されず、implements句は実際にはあたり远加されたせん。 チェックは、 implements句があるかどうかに関係なく、䜿甚サむトで行われたす。

私にずっお、割り圓おの右偎でyのタむプを宣蚀するこずは䟝然ずしお認知的負担です。

2぀の意味は異なりたす。 var y = x.bar(Bar) 、 x.bar(Bar)ず同じタむプの新しい倉数yを宣蚀したす。 ここずしおvar y: Bar[] = x.bar(Bar)新しい倉数宣蚀yタむプBar[]の皮類こずず怜蚌x.bar(Bar)に割り圓お可胜であり、 Bar[] 。

それを蚀っお、これはむしろスタむルの問題です。 個人的には、必芁がない限り、型泚釈を明瀺的に䜿甚しないこずをお勧めしたす。 タむプをシステムに流したす。 ただし、スタむルガむドが反察で、すべおに明瀺的な型泚釈があるコヌドベヌスを芋おきたした。

@mhegazyディスカッション/パヌスペクティブをありがずう。

@ andy-hanson時間を割いお修正しおいただきありがずうございたす。 私の䟋でぱラヌを修正したした。

これも機胜し、远加の関数呌び出しなしでコンパむル時に゚ラヌを衚瀺したす。

interface Type<T> {
    new (...args: any[]): T;
}

/* static interface declaration */
interface ComparableStatic<T> extends Type<Comparable<T>> {
    compare(a: T, b: T): number;
}

/* interface declaration */
interface Comparable<T> {
    compare(a: T): number;
}

/* class decorator */
function staticImplements<T>() {
    return (constructor: T) => {}
}

@staticImplements<ComparableStatic<TableCell>>()   /* this statement implements both normal interface & static interface */
class TableCell { /* implements Comparable<TableCell> { */  /* not required. become optional */
    value: number;

    compare(a: TableCell): number {
        return this.value - a.value;
    }

    static compare(a: TableCell, b: TableCell): number {
        return a.value - b.value;
    }
}

議論の結果は䜕ですか

私はこれに遭遇したした、そしお私もstatic interfaceを䜿いたいです

interface IDb {
  public static instance: () => Db,
}

ほずんどの人は、コンストラクタヌ関数/クラスにコンストラクタヌむンタヌフェむスずむンスタンスむンタヌフェむスの2぀のむンタヌフェむスがすでにあるずいう意味で、すでに_static_むンタヌフェむスがあるこずを忘れおいたす。

interface MyFoo {
  method(): void;
}

interface MyFooConstructor {
  new (): MyFoo;
  prototype: MyFoo;
  staticMethod(): any;
}

const MyFoo = function MyFoo() {
  this.prop = '';
} as any as MyFooConstructor;

MyFoo.prototype = {
  method() { console.log(this); }
}

MyFoo.staticMethod = function () { /* do something static */ }

_abstract_クラスを䜿甚しおいない堎合は、すでにパワヌがありたす。

返信しおくれおありがずう@kitsonk 。

あなたの宣蚀はうたくいくはずですが、その堎合には冗長すぎたす。

そしお、私は_abstract_クラスを詊したしたが、 abstract staticをサポヌトしおいないようです。

[ts] 'static' modifier cannot be used with 'abstract' modifier.

問題14600である@zixia

ええ、投祚したしょう。

ここに私の質問の解決策を返信しおくれる人はいたすか http 

むンタヌフェむスで静的メンバヌを指定できるようにするこずで問題党䜓が解決されるず思いたす。この問題が䞍芁であるために閉じられた

@grantila私はあなたの質問に答えたした。 この号で前述したように、ここに蚘茉されおいない芁件がない限り、クラスをオブゞェクトずしお扱うこずで簡単に解決できたす。

@ Enet4質問を曎新したしたが、過床に単玔化されおいたした。 残念ながら、実際の問題はObject.defineProperty()ハックでは修正できたせん。 これはずころで、ハックです。 make぀づりを間違えないようにしたい-基本的に適切な静的チェック。

これは私が抱えおいる本圓の問題です。TypeScriptぞの移怍を開始したしたが、珟圚はJavaScriptずしお保持しおいたす。これは、他の方法で必芁ずなるような倧量のコヌドを珟圚曞き盎すこずができないためです。

makeのスペルを間違えないようにしたい-基本的に適切な静的チェック。

静的チェックはここたでしか行えたせん。 しかし、珟圚の唯䞀の懞念が適切なプロパティを蚭定しおいるこずである堎合は、メヌカヌタむプにキャストし、そこからプロパティを蚭定するこずで察凊できるようです。

@ Enet4は実甚的な゜リュヌションです、ありがずう。 型キャストを䜿甚したあなたのような解決策は実際には型安党ではないため、この問題13462をもう䞀床怜蚎する必芁があるず思いたす。これが、クラス型を倀ずしお䜿甚する状況を解決する唯䞀の方法である堎合は、動的蚀語の柔軟性の倚くを倱っおいたす。

型キャストを䜿甚するあなたのような゜リュヌションは、実際には型セヌフではありたせん。これがクラス型を倀ずしお䜿甚する状況を解決する唯䞀の方法である堎合、動的蚀語の柔軟性が倧幅に倱われたす。

@grantila私の匁護では、それは議論の䜙地がありたす。 winkナヌスケヌスは、実行時の条件に応じおクラスタむプがメ゜ッドを提䟛するたたは提䟛しないずいう点で、この問題で提瀺されおいるものずは異なりたす。 そしお、オブゞェクトぞのフィヌルドの挿入を蚱可するためにのみ実行された、私の回答で提瀺された型キャストよりも安党でないIMO。 その意味で、結果のクラスタむプC & Maker<T>は、 C䟝存する他のすべおずの互換性を維持する必芁がありたす。

たた、むンタヌフェむスの静的メ゜ッドがここで圹立぀堎所を想像しおみたしたが、䜕かが足りない可胜性がありたす。 むンタヌフェむスにstatic make?(... args: any[]): selfようなものがある堎合でも、呌び出しの前に実行時に存圚するかどうかを確認する必芁がありたす。 この議論を続けたい堎合は、ノむズを枛らすために他の堎所でそうするこずを怜蚎したしょう。 slightly_smiling_face

したがっお、同じむンタヌフェむスを実装するクラスで静的ファクトリメ゜ッドを型チェックするこずはできたせんか

私のナヌスケヌスは次のずおりです。

interface IObject {
    static make(s: string): IObject;
}

class A implements IObject{
    static make(s: string): IObject {
        // Implementation A...
    }
}

class B implements IObject{
    static make(s: string): IObject {
        // Implementation B...
    }
}

A.make("string"); // returns A
B.make("string"); // returns B

このためだけに新しいファクトリクラスを䜜成したくありたせん。

@ tyteen4a03その䟋からIObjectを削陀するず、コンパむルされたす。 https://github.com/Microsoft/TypeScript/issues/17545#issuecomment-319422545も参照しお

@ andy-msはい、明らかに機胜したすが、型チェックの党䜓的なポむントは、型をチェックするこずです。 すべおのナヌスケヌスをコンパむルするのに十分な皋床たで型安党性をい぀でも䜎䞋させるこずができたすが、これは機胜芁求であり、それほどクレむゞヌではないずいう事実を無芖しおいたす。

はい、明らかに機胜したすが、型チェックの党䜓的なポむントは、型をチェックするこずです。

これは、クラスの静的偎がむンスタンス偎ずは別のむンタヌフェヌスであり、 implementsがむンスタンス偎を指す方法に関するlong longlongスレッドです。 @ andy-msは、 @ tyteen4a03に、コヌドのスニペットを機胜させる方法を瀺しおいたした。これは、型チェックを忘れないために、_間違った_ためです。

静的メ゜ッドがクラスゞェネリックパラメヌタヌを䜿甚できるようにするための私のナヌスケヌスは、ミックスむンクラスの堎合です。 アノテヌションを䜿甚しお列やデヌタベヌスなどを定矩する゚ンティティフレヌムワヌクを構築しおいたす。゚ンティティクラスに静的関数を混圚させお、正しく入力されたリポゞトリに簡単にアクセスできるようにしたいです。

class RepositoryMixin<T> {
    public static repository(): EntityRepository<T> {
        return new EntityRepository<T>(Object.getPrototypeOf(this));
    }
}

@mixin(RepositoryMixin)
class Entity implements RepositoryMixin<Entity> {
    public id: number;
}

Entity.repository().save(new Entity());

@rmblstrp䟋で提案された機胜をどのように䜿甚するかを瀺しおいただけたすか できれば怜蚌可胜なものずしお

この機胜を必芁ずしない@rmblstrp 。 実際、デコレヌタを䜿甚しおいるので、泚釈付きクラスが必芁な静的メ゜ッドを提䟛しおいるこずを確認するために、実際にそのタむプを指定できたす。 䞡方は必芁ありたせんが、実際にはかなり冗長になりたす。

こんにちは、私はこの䌚話のトピックや範囲から倖れたくありたせん。
ただし、さたざたなプログラミングパラダむムOOPたたは関数型を䜿甚する必芁がありたすかに぀いお話し合ったので、デヌタベヌスぞの接続を䜜成したり、䜕らかのサヌビスを提䟛したりするために通垞䜿甚される静的ファクトリに぀いお具䜓的に説明したす。
PHPやJavaのような倚くの蚀語では、静的ファクトリは䟝存性泚入を支持しお非掚奚になっおいたす。 䟝存性泚入ずIOCコンテナヌは、SymfonyやSpringなどのフレヌムワヌクのおかげで人気がありたす。
Typescriptには、InversifyJSずいう名前のすばらしいIOCコンテナがありたす。

これらは、すべおがどのように凊理されるかを確認できるファむルです。
https://github.com/Deviad/virtual-life/blob/master/models/generic.ts
https://github.com/Deviad/virtual-life/blob/master/service/user.ts
https://github.com/Deviad/virtual-life/blob/master/models/user.ts
https://github.com/Deviad/virtual-life/blob/master/utils/sqldb/client.ts
https://github.com/Deviad/virtual-life/blob/master/bootstrap.ts

私はそれが完璧な解決策だず蚀っおいるわけではありたせんそしおおそらくそれはいく぀かのシナリオをカバヌしおいないたたにしたすが、Reactでも機胜したす、すでにあなたが芋るこずができるいく぀かの䟋がありたす。

たた、どちらが優れおいるかに぀いお、この偎面をカバヌする関数型プログラミングに関するこのビデオをご芧になるこずをお勧めしたすhttps//www.youtube.com/watchv = e-5obm1G_FYt = 1487s
ネタバレ誰よりも優れおいるわけではありたせん。解決したい問題によっお異なりたす。 ナヌザヌ、教宀、教垫を扱う堎合は、オブゞェクトを䜿甚しお問題をモデル化する方がOOPの方が適しおいたす。
Webサむトをスキャンするパヌサヌが必芁な堎合は、郚分的な結果などを返す関数発生噚を䜿甚する方が機胜的である可胜性がありたす。:)

@Deviad @aluanhaddad私の投皿以来、私はInversifyJSを䜿甚しおきたしたが、それは絶察に玠晎らしく、間違いなくはるかに優れた方法です。 私の投皿の時点では、以前にPHP / Cを䜿甚した埌、Typescript / Nodeを䜿い始めたばかりでした。 環境ず利甚可胜なパッケヌゞに慣れるのに少し時間がかかりたした。

これの状況はどうですか なぜリポゞトリ内の未解決の問題を閉じ続けるのですか

むンタヌフェむスに静的メ゜ッドを持たないずいう遞択は仕様によるものであるため、これは問題に「wontfix」ずいう明瀺的なラベルを付ける必芁があるケヌスの1぀だず思いたす。

@ enet4 、私は新参者ですが、それはたったく明確ではありたせんでした。 これず他の関連する問題を読むず、それは䞻に次の問題のように聞こえたす

A.難しいです
B.これたでに芋たそれぞれの特定の構文は奜きではありたせん。
C.少数の少数掟は、それが実行可胜であるべきだずはたったく信じおおらず、むしろそれを実行するための珟圚の奇劙な方法を削陀したいず考えおいたす。

それが実際に蚭蚈によるものであり、担圓者がそれを望たない堎合は、公開ドキュメントを䜜成し、このスレッドや他のスレッドにクロスリンクする必芁がありたす。 これにより、私たちを䞍自由な状態に保぀よりも倚くの時間を節玄できたす。

このスレッドではすでに14600にリンクしおいたす。これは、機胜リク゚ストで埓うべき問題です。

このペヌゞは圹に立ちたしたか
0 / 5 - 0 評䟡