Typescript: モゞュヌルにむンタヌフェヌスの実装を蚱可する

䜜成日 2014幎08月10日  Â·  34コメント  Â·  ゜ヌス: microsoft/TypeScript

モゞュヌルがimplementsキヌワヌドを䜿甚しおむンタヌフェヌスを実装できる堎合に圹立ちたす。 構文 module MyModule implements MyInterface { ... } 。

䟋

interface Showable {
    show(): void;
}
function addShowable(showable: Showable) {

}

// This works:
module Login {
    export function show() {
        document.getElementById('login').style.display = 'block';
    }
}
addShowable(Login);

// This doesn't work (yet?)
module Menu implements Showable {
    export function show() {
        document.getElementById('menu').style.display = 'block';
    }
}
addShowable(Menu);
Suggestion help wanted

最も参考になるコメント

1぀のナヌスケヌスは、アプリケヌションの起動時にディレクトリをスキャンしおモゞュヌルを探し、それらのモゞュヌルすべおが特定の圢状を゚クスポヌトするこずを期埅するフレヌムワヌクずツヌルの堎合です。

たずえば、 Next.jsはペヌゞモゞュヌルの./pages/**/*.{ts,tsx}をスキャンし、ファむル名に基づいおルヌトを生成したす。 各モゞュヌルが正しいものを゚クスポヌトするこずを確認するのはあなた次第ですデフォルトの゚クスポヌトずしおNextPage 、およびconfigずいう名前のオプションのPageConfig゚クスポヌト

import { NextPage, PageConfig } from 'next'

interface Props { userAgent?: string }

const Home: NextPage<Props> = ({ userAgent }) => (<main>...</main>)

Page.getInitialProps = async ({ req }) => {
  const userAgent = req ? req.headers['user-agent'] : navigator.userAgent
  return { userAgent }
}

export default Page

export const config: PageConfig = {
  api: { bodyParser: false }
}

代わりに、 implements NextPageModule<Props>ように、モゞュヌル党䜓の゚クスポヌト圢状を䞊郚近くの1行で宣蚀できるず䟿利です。

別の考えTypeScript構成で、特定のパタヌン ./pages/**/*.{ts,tsx} に䞀臎するすべおのファむルが特定の゚クスポヌト圢状を実装する必芁があるこずを指定する方法があれば興味深いでしょう。たずえば、 pagesディレクトリ内にあるずいう理由だけでチェックしたした。 しかし、このアプロヌチの前䟋があるかどうかはわかりたせん。混乱する可胜性がありたす。

党おのコメント34件

これは倖郚モゞュヌルでどのように機胜したすか 人々がそれを内郚で䜿甚できるようになるず、倖郚でも䜿甚したいず思うでしょう。

それは良い質問です。 どの構文が最適かはわかりたせんが、いく぀かの提案がありたす。

implements Showable; // I would prefer this one.
module implements Showable;
export implements Showable;

゚クスポヌト割り圓おを䜿甚する堎合、゚クスポヌトするものはすでに別の堎所にimplementsを持っおいる可胜性があるため、゚クスポヌト割り圓おを䜿甚しない倖郚モゞュヌルでのみ蚱可する必芁がありたす。

承認されたした。 構文を優先したす

export implements Showable;

そしお、これはファむルexport =割り圓おには䞍芁であるこずに同意したした。

さらにいく぀かの質問

  • モゞュヌルが宣蚀サむトで型を持぀こずを蚱可しおいるので、モゞュヌルが䜿甚サむトでも型を持぀こずを蚱可するべきではありたせん。 䟋えば
declare module "Module" implements Interface { }

import i : Interface = require("Module");
  • マヌゞされた宣蚀をどうしたすかすべおの宣蚀の集合䜓にむンタヌフェヌスを適甚する必芁がありたすか 可芖性が䞀臎しない堎合はどうなりたすか
    䟋えば
module Foo {
    export interface IBar {
        (a:string): void;
    }

    export module Bar implements IBar {  // should this be an error?
        export interface Interface {}
    }    

    function Bar(a: string) : void { }  // not exported
}

var bar: Foo.IBar = Foo.Bar;

アンビ゚ント倖郚モゞュヌルで蚱可する必芁がありたす。 これらのモゞュヌルでは、私の意芋では2぀の構文を蚱可する必芁がありたす。

declare module "first" implements Foo { }
declare module "second"  {
  interface Bar { }
  export implements Bar; // this syntax is necessary, with the first syntax you can't reference Bar.  
}

たたは、 {開く前に、Barをimplements句のスコヌプに含める必芁がありたすか

型情報をモゞュヌル自䜓に远加できるので、むンポヌトステヌトメントに型情報を远加するこずは私の意芋ではあたり圹に立ちたせん。

たた、マヌゞされた宣蚀の堎合、implements句を含むモゞュヌルブロックはむンタヌフェむスを実装する必芁がありたす。 これにより、可芖性の問題も防止されたす。

これは2159ずどのように関連しおいたすか 名前空間はむンタヌフェヌスを実装したすか

@jbondcこれがあれば、名前空間にも適甚されたす。 内郚モゞュヌルず名前空間は同圢であるず考える必芁がありたす。

「名前空間」がむンタヌフェヌスを実装できる実装パスをたどっおよろしいですか

うわヌ、これはかなり長い間承認されおいたす。 @ RyanCavanaugh 、 @ DanielRosenwasser 、 @ mhegazyは、考え盎したり埮調敎したりしない限り、おそらくすぐに実装したす。

私は以前の懐疑論を撀回し、それがもたらす新しい構造的可胜性のために実際に退出したした。

それに沿っお、実装を宣蚀するブロックだけでなく、むンタヌフェヌスの集合䜓のむンタヌフェヌスを匷制するこずを怜蚎しおください-名前空間/モゞュヌルの性質は分散され、倚くの重芁なコンポヌネントが含たれたす。 これを䜿甚できるようにしたいのですが、名前空間/モゞュヌル党䜓を同じファむルで定矩したくないのは確かです。 その堎合、なぜクラスを䜿甚しないのですか

@ Elephant-Vesselモゞュヌル、名前空間、パッケヌゞ、機胜、たたは...に぀いお話しおいるのかどうかはわかりたせん。

@aluanhaddadどういう意味ですか

぀たり、このディスカッションが開始された時点では、モゞュヌルは今日の意味を意味しおいたせんでした。 珟圚、名前空間ずいう甚語を䜿甚しお、OPでモゞュヌルずしお蚘述されおいるものを指したすが、モゞュヌルはより正確で互換性のない意味を持っおいたす。 それで、この実装に参加しおいる耇数のファむルに぀いお話すずき、名前空間たたはモゞュヌルを参照しおいたすか

名前空間に぀いお蚀及しおいたす。 私はこのスレッドの歎史に準拠したかったのだず思いたす。緩たないようにしお申し蚳ありたせん:)たたは、考えおみるず、頭の䞭に「モゞュヌル」ずいう䞀般的な甚語があり、セットで構成される高レベルのナニットを衚しおいたす。システムに特定の高レベルの機胜を提䟛するために組み立おられたサブコンポヌネントの。 しかし、私は「名前空間」を䜿甚するだけで倧​​䞈倫です。

したがっお、typescriptの構造抂念の名前空間を利甚しお、他の[_genericmodules_]たたはクラスを含むこずができる[_genericmodules_]を蚘述し、制玄ず期埅を蚭定できるようにしたいず思い

私の垌望は、システムでより高いレベルの構造的期埅をより適切に衚珟できるようになるこずです。 クラスは拡匵性が䜎く、システムのアトミックコンポヌネントずしおは問題ありたせんが、システム内の高レベルの組織構造は、むンスタンス化および継承されるように蚭蚈されおいるため、クラスで衚珟するのは適切ではないず思いたす。 。 ふわふわすぎたす。

倧隒ぎせずに、システムの高次構造を説明するためのシンプルでクリヌンな方法をいただければ幞いです。 できれば、オプションの方向性の可芖性の制玄だけが倧隒ぎになりたす。 _MySystem.Infrastructure_から_MySystem.ClientApplication_を参照できないようにするのず同じですが、その逆は問題ありたせん。 それから私たちはどこか゚キサむティングな堎所に行き始めたす。

@ Elephant-明確にしおくれおありがずう。 これは非垞に䟡倀があり、クラスタむプはここでは適切なアプロヌチではないこずに同意したす。 名前空間は、ラむブラリレベルで抂念的にシングルトンであるものを衚すため、むンスタンス化に぀いお話すずきは頭に釘付けになるず思いたす。 これを匷制するこずはできたせんが、抂念的には、耇数のむンスタンス化を「暗瀺」しないものがあるず䟿利です。

@ Elephant-Vesselに同意したす。 TypeScriptを別のJavaず間違えやすいのですが、すべおの制玄が単䞀のクラス構造で衚珟されおいたすが、TSには、非垞に匷力でセマンティックなゆがみを排陀する、はるかに広い「圢状」の抂念がありたす。 残念ながら、モゞュヌルに制玄を課すこずができないず、開発者はモゞュヌルずしおより適切に衚珟されるもののクラスパタヌンに戻るこずを䜙儀なくされる傟向がありたす。

たずえば、単䜓テストの堎合、特定の実行コンテキストに代替実装を提䟛できるように、モゞュヌルにいく぀かの「圢状」぀たり制玄を衚珟できるず非垞に圹立ちたす。 さお、構造/チェックされた方法でそれを行う唯䞀の方法は、クラスベヌスのDIla Springなどに戻り、すべおをクラスにするしたがっおむンスタンス化できるこずです。

ずにかく、私は@ Elephant-Vesselを蚀い換えおいたすが、TSに察する単䞀の願いがあれば、それはこれになりたす。

この鳥に぀いお䜕か蚀葉はありたすか 私もこの問題を抱えおいたす

すっごく、うヌん、それは単玔なケヌスではないでしょうか

export {} as IFooBar;

その構文の䜕が問題になっおいたすか 構文はすでに承認されおいるず思いたす。

export implements IFooBar

ずにかくそれを楜しみにしおいたす

これはもう入孊/䞊陞したしたか これはクヌルな機胜になるでしょう

どうすればこれを進めるこずができたすか その信じられないほど匷力です。 喜んでお手䌝いしたす

このバヌブにノォルプはありたすか 今のずころ私が持っおいる質問の1぀は、デフォルトの゚クスポヌト甚のむンタヌフェむスをどのように宣蚀できるかずいうこずです。 䟋えば

export default {}

私はただできるず思いたす

const x: MyInterface = {}
export default x;

これはほずんどのTSファむルで機胜したすが、問題は、最初にJSをコヌディングしおいお、埌でTSに移行するこずを蚈画しおいる堎合、これはあたりうたく機胜しないこずです。

私が考えおいたもう1぀のこずは、実装する名前空間に぀いおはどうでしょうか。 䜕かのようなもの

export namespace Foo implements Bar {

}

Barは_abstract_名前空間だず思いたすlolidk

この質問が䜕床も出おくるのを芋お、私たちは皆、ただ1぀のこずを探しおいるず思いたす。
むンタヌフェむスで静的メンバヌをサポヌトしたす。
その堎合は、静的メンバヌずむンタヌフェむスを備えたクラスを䜿甚できたす。これは、ここで実行しようずしおいるこずずほが同じです。

いずれにせよ、むンタヌフェむスに静的サポヌトを远加するか、モゞュヌルのむンタヌフェむスサポヌトを远加する必芁がありたす。

@shiapetelいやそうじゃない。

できるよ

export default <T>{
  foo: Foo,
  bar: Bar
}

しかし、それは私たちが探しおいるものではありたせん。 私たちは特に探しおいたす

export const foo : Foo = {};
export const bar : Bar = {};

しかし、珟圚、モゞュヌルにfooずbarを゚クスポヌトするように匷制するメカニズムはありたせん。 実際、モゞュヌルが正しいデフォルト倀を゚クスポヌトするように匷制するメカニズムもありたせん。

むンタヌフェむスが静的メンバヌをサポヌトしおいる堎合は、以䞋から継承した静的foo / barを持぀クラスを䜿甚できたす。
むンタヌフェヌスILoveFooBar {
static fooFooType;
静的バヌBarType;
}

正しい
それが私が意味したこずです、私はそれがあなたの状況で圹立぀ず思いたす-私はそれが私の䞭で間違いなく圹立぀こずを知っおいたす。

むンタヌフェむスの@shaipetel静的メンバヌは間違いなく圹立぀かもしれたせんが、おそらくこのナヌスケヌスではそうではありたせん。

この問題は、誰かが実装に取り​​掛かるのを埅っおいるだけですか

1぀のナヌスケヌスは、アプリケヌションの起動時にディレクトリをスキャンしおモゞュヌルを探し、それらのモゞュヌルすべおが特定の圢状を゚クスポヌトするこずを期埅するフレヌムワヌクずツヌルの堎合です。

たずえば、 Next.jsはペヌゞモゞュヌルの./pages/**/*.{ts,tsx}をスキャンし、ファむル名に基づいおルヌトを生成したす。 各モゞュヌルが正しいものを゚クスポヌトするこずを確認するのはあなた次第ですデフォルトの゚クスポヌトずしおNextPage 、およびconfigずいう名前のオプションのPageConfig゚クスポヌト

import { NextPage, PageConfig } from 'next'

interface Props { userAgent?: string }

const Home: NextPage<Props> = ({ userAgent }) => (<main>...</main>)

Page.getInitialProps = async ({ req }) => {
  const userAgent = req ? req.headers['user-agent'] : navigator.userAgent
  return { userAgent }
}

export default Page

export const config: PageConfig = {
  api: { bodyParser: false }
}

代わりに、 implements NextPageModule<Props>ように、モゞュヌル党䜓の゚クスポヌト圢状を䞊郚近くの1行で宣蚀できるず䟿利です。

別の考えTypeScript構成で、特定のパタヌン ./pages/**/*.{ts,tsx} に䞀臎するすべおのファむルが特定の゚クスポヌト圢状を実装する必芁があるこずを指定する方法があれば興味深いでしょう。たずえば、 pagesディレクトリ内にあるずいう理由だけでチェックしたした。 しかし、このアプロヌチの前䟋があるかどうかはわかりたせん。混乱する可胜性がありたす。

むンタヌフェむスを実装する単玔なモゞュヌルだけが必芁な堎合、シングルトンクラスを䜜成したくなるこずがよくありたす。 これに察凊するための最善のヒントはありたすか

@RyanCavanaugh @DanielRosenwasser
この問題に取り組みたいず思いたす。 解決策のヒントや芋回す堎所を教えおください。

2020幎の芳点から、この考える、私は、ifの代わりに、䞍思議export implements Showable我々再䜿甚typeし、蚱可するexport識別子ずしお 今日、これは無効な構文であるため、既存のコヌドベヌスを螏む可胜性はほずんどありたせん。

次に、むンポヌト構文を取埗したす。

// Can re-use the import syntax
type export = import("webpack").Config

そうすれば、宣蚀は簡単に曞くこずができたす。

// Can use normal literals
type export = { test: () => string, description: string }

// Generics are easy
type export = (props: any) => React.SFC<MyCustomModule>

JSDocの同等物もどうあるべきかを考える䟡倀もありたす。

/** <strong i="17">@typedef</strong> {import ("webpack").Config} export */

^にはいく぀かの泚意事項がありたす。䌚議から出おきた興味深い点の1぀は、これが唯䞀のこずではなく、ナヌスケヌスであるより䞀般的なツヌルを構築できるずいうアむデアでした。

たずえば、型の互換性のために型アサヌション挔算子がある堎合、それをモゞュヌルの゚クスポヌトの䞡方に䜿甚でき、䞀般的に、型が垌望どおりに䞀臎するこずを確認できたす。 䟋えば

type assert is import("webpack").Config

const path = require('path');

export default {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js'
  }
};

タヌゲットの欠劂は、トップレベルのスコヌプでそれを適甚するこずを意味したす。 これは、コンテキストタむピングを提䟛するために䜿甚できたすたずえば、 export default { en|オヌトコンプリヌトを取埗したす

ただし、独自のタむプを怜蚌する堎合にも圹立ちたす。

import {someFunction} from "./example"

type assert ReturnType<typeof someFunction> is string

JSDocの同等物もどうあるべきかを考える䟡倀もありたす。
js /** <strong i="7">@typedef</strong> {import ("webpack").Config} export */

@moduleはJSDocに盞圓するず思いたす。 ファむルの先頭には次のものが必芁です。
js /** <strong i="12">@module</strong> {import("webpack").Config} moduleName */

参照 https 

Storybook v6は、 Component StoryFormatず呌ばれる構造化モゞュヌルに基づくアプロヌチに倉曎されたした。 コヌドベヌス内のすべおの.stories.js/tsモゞュヌルには、タむプMetaデフォルトの゚クスポヌトが含たれおいるず予想されたす。

この期埅をグロヌバルな方法で衚珟する方法がなく、デフォルトの゚クスポヌトを入力する際の

@jonrimmerのポむントに远加するには、 moduleを耇補する特定のtype defaultを゚クスポヌトするず、ツリヌの揺れに問題が発生したす。

Webpackはimport * as Foo揺さぶる問題はありたせん。 ただし、すべおの静的メンバヌを䜿甚しおexport default const = {}たたはexport default class ModuleName {で同じこずを実行しようずしおも、未䜿甚のむンポヌトは削陀されたせん。

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