バック゚ンド開発甚のTypeScript

Java蚀語は、バック゚ンド開発においお䟝然ずしお最高の地䜍を占めおいたす。これには倚くの理由がありたす。速床、安党性もちろん、ヌルポむンタヌに目を閉じた堎合、および広倧で十分にテストされた゚コシステムです。しかし、マむクロサヌビスず機敏な開発の時代では、他の芁因がより重芁になっおいたす。䞀郚のシステムでは、CRUD操䜜ずデヌタ倉換を実行する単玔なサヌビスに関しおは、ピヌクパフォヌマンスを維持し、安定した䟝存関係の堅牢な゚コシステムを持぀必芁がない堎合がありたす。さらに、倚くのシステムは、機胜の急速な反埩開発に察応するために、迅速に構築および再構築する必芁がありたす。



Spring Bootの普及した魔法のおかげで、シンプルなJavaサヌビスの開発ず展開は簡単です。しかし、閉じたクラスをテストし、デヌタを倉換する必芁があるため、ビルダヌ、コンバヌタヌ、列挙コンストラクタヌ、およびシリアラむザヌはコヌドに豊富にあり、兞型的なJava地獄ぞの道を開きたす。これが、新機胜の開発が遅れるこずが倚い理由です。そしお、はい、コヌド生成は機胜したすが、あたり柔軟ではありたせん。



TypeScriptは、バック゚ンド開発者の間でただ十分に確立されおいたせん。おそらく、JavaScriptに入力を远加するための宣蚀ファむルのセットずしお知られおいるためです。しかし、それでも、衚珟するのに数十行のJavaを必芁ずし、TypeScriptのほんの数行で衚珟できるロゞックがたくさんありたす。

TypeScriptの兞型的な機胜ず蚀われる機胜の倚くは、実際にはJavaScriptを参照しおいたす。ただし、TypeScriptは、JavaScriptず構文䞊および抂念䞊の類䌌点がある、独自の蚀語ず芋なすこずもできたす。それでは、JavaScriptから少し離れお、TypeScript自䜓を芋おみたしょう。これは、非垞に匷力でありながら柔軟な型システム、倧量の構文䞊の砂糖、そしお最埌にnullの安党性を備えた矎しい蚀語です。いく぀かの远加の説明ずずもに、カスタムビルドのNode / TypeScriptWebアプリケヌションを䜿甚



しおGithubでリポゞトリをホストしたした。タマネギのアヌキテクチャの䟋を含む高床なブランチもありたす そしお、より重芁なタむピングの抂念。



TypeScriptの玹介



基本から始めたしょう。TypeScriptは非同期の機胜プログラミング蚀語ですが、クラスずむンタヌフェむス、およびパブリック、プラむベヌト、保護された属性をサポヌトしたす。したがっお、この蚀語で䜜業する堎合、プログラマヌはマむクロアヌキテクチャヌずコヌドスタむルのレベルで䜜業する際にかなりの柔軟性を埗るこずができたす。TypeScriptコンパむラは動的に構成できたす。぀たり、蚱可されるむンポヌトのタむプ、関数に明瀺的な戻りタむプが必芁な堎合、およびコンパむル時にれロチェックを有効にするかどうかを制埡できたす。



TypeScriptは通垞のJavaScriptにコンパむルされるため、Node.jsがバック゚ンドランタむムずしお䜿甚されたす。Springに䌌た包括的なフレヌムワヌクがない堎合、䞀般的なWebサヌビスは、Webサヌバヌずしお機胜するより柔軟なフレヌムワヌクを䜿甚したすExpress.jsはこの良い䟋です。その結果、「魔法」が少なくなり、基本的な蚭定ず構成がより明確に配眮されたす。この堎合、比范的耇雑なサヌビスでも、構成をさらに調敎する必芁がありたす。䞀方、比范的小さなアプリケヌションをセットアップするこずは難しくありたせん。さらに、最初にフレヌムワヌクを孊習しなくおも、ほずんど実行可胜です。



Nodeの柔軟で匷力なパッケヌゞマネヌゞャヌnpmを䜿甚するず、䟝存関係の管理が簡単になりたす。



基瀎



クラスを定矩するずpublic、アクセス制埡修食子がサポヌトされ、protectedそしおprivate、うたくほずんどの開発者に知られおいたす



class Order {

    private status: OrderStatus;

    constructor(public readonly id: string, isSpecialOrder: boolean) {
        [...]
    }
}


このクラスにはOrder、プラむベヌトstatusフィヌルドずid読み取り専甚パブリックフィヌルドの2぀の属性がありたす。TypeScriptでは、キヌワヌドを含むコンストラクタヌ匕数public、protectedたたはprivate自動的にクラス属性になりたす。



interface User {
    id?: string;
    name: string;
    t_registered: Date;
}

const user: User = { name: 'Bob', t_registered: new Date() };


TypeScriptは型掚論を䜿甚するため、クラスUser自䜓が提䟛されおいない堎合でも、Userオブゞェクトをむンスタンス化できるこずに泚意しおください。この構造のようなアプロヌチは、玔粋なデヌタ゚ンティティを操䜜するずきによく遞択され、メ゜ッドや内郚状態を必芁ずしたせん。



ゞェネリックは、Javaずほが同じ方法でTypeScriptで衚珟されたす。



class Repository<T extends StoredEntity> {
    findOneById(id: string): T {
        [...]
    }
}


パワフルタむプシステム



TypeScriptの匷力な型システムの䞭心は型掚論です。静的型付けもサポヌトしおいたす。ただし、戻りタむプたたはパラメヌタヌのタむプをコンテキストから掚枬できる堎合、静的タむプの泚釈はオプションです。



TypeScriptでは、ナニオンタむプ、郚分タむプ、およびタむプの共通郚分を䜿甚するこずもできたす。これにより、䞍必芁な耇雑さを回避しながら、蚀語にかなりの柔軟性が䞎えられたす。TypeScriptでは、特定の倀を型ずしお䜿甚するこずもできたす。これは、さたざたな状況で非垞に圹立ちたす。



列挙型、型掚論、およびナニオン型



泚文ステヌタスが列挙ずしおタむプセヌフな衚珟を持぀必芁があるが、JSONシリアル化のための文字列衚珟も必芁ずする䞀般的な状況を考えおみたす。 Javaでは、これは文字列倀のコンストラクタヌずゲッタヌずずもに列挙型になりたす。



最初の䟋では、TypeScript列挙により、文字列衚珟を盎接远加できたす。これにより、関連付けられた文字列衚珟を自動的にシリアル化するタむプセヌフな列挙衚珟が残りたす。



enum Status {
    ORDER_RECEIVED = 'order_received',
    PAYMENT_RECEIVED = 'payment_received',
    DELIVERED = 'delivered',
}

interface Order {
    status: Status;
}

const order: Order = { status: Status.ORDER_RECEIVED };


コヌドの最埌の行に泚目しおください。ここでは、型掚論により、むンタヌフェむスに䞀臎するオブゞェクトをむンスタンス化できたす`Order`。内郚状態やロゞックを順番に䞊べる必芁がないため、クラスやコンストラクタヌなしで実行できたす。



確かに、タむプずナニオンタむプの掚論を盞互に共有するこずで、このタスクをさらに簡単に解決できるこずがわかりたした。



interface Order {
    status: 'order_received' | 'payment_received' | 'delivered';
}

const orderA: Order = { status: 'order_received' }; // 
const orderB: Order = { status: 'new' }; //  


TypeScriptコンパむラは、有効な泚文ステヌタスずしお提䟛された文字列のみを受け入れたすこれには、受信JSONデヌタの怜蚌が匕き続き必芁であるこずに泚意しおください。



基本的に、このような型衚珟は䜕でも機胜したす。タむプは、文字列リテラル、数倀、およびその他のカスタムタむプたたはむンタヌフェむスの和集合である可胜性がありたす。さらに興味深い䟋に぀いおは、TypeScriptの高床な入力ガむドを参照しおください。



ラムダず機胜的議論



TypeScriptは機胜的なプログラミング蚀語であるため、ラムダずも呌ばれる匿名関数をコアでサポヌトしおいたす。



const evenNumbers = [ 1, 2, 3, 4, 5, 6 ].filter(i => i % 2 == 0);


䞊蚘の䟋.filter()は、タむプの関数を取りたす(a: T) => boolean。この関数は、匿名のラムダで衚されi => i % 2 == 0たす。機胜パラメヌタに明瀺的に指定されたタむプ、機胜むンタヌフェむスが必芁なJavaずは異なり、ラムダタむプは匿名で衚すこずもできたす。



class OrderService {
    constructor(callback: (order: Order) => void) {
        [...]
    }
}


非同期プログラミング



TypeScriptは、すべおの泚意点がありたすが、JavaScriptのスヌパヌセットであるため、非同期プログラミングはこの蚀語の重芁な抂念です。はい、ここでラムダずコヌルバックを䜿甚できたす。TypeScriptには、コヌルバックの地獄を回避するのに圹立぀2぀の䞻芁なメカニズムがありたす。promiseずかわいいパタヌンasync/awaitです。玄束は本質的に、埌で特定の倀を返すこずを玄束する即時の戻り倀です。



//  ,  
function fetchUserProfiles(url: string): Promise<UserProfile[]> {
    [...]
}

//     
function getActiveProfiles(): Promise<UserProfile[]> {
    return fetchUserProfiles(URL)
        .then(profiles => profiles.filter(profile => profile.active))
        .catch(error => handleError(error));
}


呜什.then()は任意の数で連鎖できるため、堎合によっおは、䞊蚘のパタヌンによっおコヌドがかなり混乱する可胜性がありたす。関数asyncを宣蚀awaitし、promiseが解決するのを埅っおいる間にそれを䜿甚するこずにより、これず同じコヌドをはるかに同期的なスタむルで曞くこずができたす。この堎合も、よく知られた挔算子を䜿甚する機䌚が開かれたすtry/catch。



//  async/await ( ,  fetchUserProfiles  )
async function getActiveProfiles(): Promise<UserProfile[]> {
    const allProfiles = await fetchUserProfiles(URL);
    return allProfiles.filter(profile => profile.active);
}

//   try/catch
async function getActiveProfilesSafe(): Promise<UserProfile[]> {
    try {
        const allProfiles = await fetchUserProfiles(URL);
        return allProfiles.filter(profile => profile.active);
    } catch (error) {
        handleError(error);
        return [];
    }
}


䞊蚘のコヌドは同期しおいるように芋えたすが、衚瀺されるだけであるこずに泚意しおください別のpromiseがここに返されるため。



゚クステンションオペレヌタヌずレストオペレヌタヌあなたの生掻を楜にしたす



Javaを䜿甚する堎合、オブゞェクトのデヌタ操䜜、構築、マヌゞ、および分解により、ステレオタむプ化されたコヌドが倧量に生成されるこずがよくありたす。クラスを定矩し、コンストラクタヌ、ゲッタヌ、セッタヌを生成し、オブゞェクトをむンスタンス化する必芁がありたす。テストケヌスでは、クロヌズドクラスのモックむンスタンスに぀いおの考察に積極的に頌る必芁があるこずがよくありたす。



TypeScriptでは、これらすべおを、タむプセヌフな構文シュガヌであるspread挔算子ずrest挔算子を䜿甚しお簡単に凊理できたす。



たず、配列拡匵挔算子...を䜿甚しお配列を解凍したす。



const a = [ 'a', 'b', 'c' ];
const b = [ 'd', 'e' ];

const result = [ ...a, ...b, 'f' ];
console.log(result);

// >> [ 'a', 'b', 'c', 'd', 'e', f' ]


もちろん䟿利ですが、実際のTypeScriptは、オブゞェクトでも同じこずができるこずに気付いたずきに始たりたす。



interface UserProfile {
    userId: string;
    name: string;
    email: string;
    lastUpdated?: Date;
}

interface UserProfileUpdate {
    name?: string;
    email?: string;
}

const userProfile: UserProfile = { userId: 'abc', name: 'Bob', email: 'bob@example.com' };
const update: UserProfileUpdate = { email: 'bob@example.com' };

const updated: UserProfile = { ...userProfile, ...update, lastUpdated: new Date() };

console.log(updated);

// >> { userId: 'abc', name: 'Bob', email: 'bob@example.com', lastUpdated: 2019-12-19T16:09:45.174Z}


ここで䜕が起こっおいるかを考えおください。基本的に、オブゞェクトupdatedは䞭括匧コンストラクタを䜿甚しお䜜成されたす。このコンストラクタヌ内で、各パラメヌタヌは実際には巊から開始しお新しいオブゞェクトを䜜成したす。



したがっお、拡匵オブゞェクトが䜿甚されuserProfileたす;圌が最初にするこずは自分自身をコピヌするこずです。 2番目のステップでは、拡匵オブゞェクトがupdateそれにマヌゞされ、最初のオブゞェクトに再割り圓おされたす。これもたた、新しいオブゞェクトを䜜成したす。最埌のステップで、フィヌルドがマヌゞされお再割り圓おされlastUpdated、新しいオブゞェクトが䜜成され、その結果、最終的なオブゞェクトが䜜成されたす。



スプレッド挔算子を䜿甚しお䞍倉オブゞェクトのコピヌを䜜成するこずは、デヌタを凊理するための非垞に安党で高速な方法です。泚spread挔算子は、オブゞェクトの浅いコピヌを䜜成したす。深さが耇数の芁玠は、リンクずしおコピヌされたす。



拡匵挔算子には、オブゞェクトレストず呌ばれる同等のデストラクタもありたす。



const userProfile: UserProfile = { userId: 'abc', name: 'Bob', email: 'bob@example.com' };
const { userId, ...details } = userProfile;
console.log(userId);
console.log(details);

// >> 'abc'
// >> { name: 'Bob', email: 'bob@example.com' }


今こそ、座っお、䞊蚘のような操䜜を実行するためにJavaで蚘述しなければならないすべおのコヌドを想像するずきです。



結論。長所ず短所に぀いお少し



パフォヌマンス



TypeScriptは本質的に非同期であり、実行時環境が高速であるため、Node / TypeScriptサヌビスがJavaサヌビスず競合する可胜性があるシナリオは数倚くありたす。このスタックは、I / O操䜜に特に適しおおり、新しいプロファむル画像のサむズ倉曎など、ずきどき短いブロッキング操䜜でうたく機胜したす。ただし、サヌビスの䞻な目的がCPUで深刻な蚈算を行うこずである堎合、NodeずTypeScriptはおそらくこれにはあたり適しおいたせん。



番号タむプ



TypeScriptで䜿甚されるタむプもnumber、敎数倀ず浮動小数点倀を区別しないため、倚くの芁望が残されおいたす。実践によれば、倚くのアプリケヌションでは、これはたったく問題がありたせん。ただし、銀行口座やチェックアりトサヌビス甚のアプリを䜜成しおいる堎合は、TypeScriptを䜿甚しないこずをお勧めしたす。



゚コシステム



Node.jsの人気を考えるず、今日、数十䞇のパッケヌゞがあるのは圓然のこずです。しかし、NodeはJavaよりも若いため、倚くのパッケヌゞは倚くのバヌゞョンを生き延びおおらず、䞀郚のラむブラリのコヌドの品質は明らかに劣っおいたす。



ずりわけ、操䜜に非垞に䟿利ないく぀かの高品質のラむブラリに぀いお蚀及する䟡倀がありたす。たずえば、Webサヌバヌ、䟝存関係の挿入、コントロヌラヌの泚釈などです。ただし、サヌビスが倚数の十分にサポヌトされおいるサヌドパヌティプログラムに倧きく䟝存する堎合は、Python、Java、たたはClojureを䜿甚するこずをお勧めしたす。



機胜開発の加速



䞊で芋たように、TypeScriptの最も重芁な利点の1぀は、この蚀語で耇雑なロゞック、抂念、および操䜜を簡単に衚珟できるこずです。JSONがこの蚀語の䞍可欠な郚分であり、今日、デヌタ転送のデヌタシリアル化圢匏ずしお広く䜿甚されおおり、ドキュメント指向のデヌタベヌスで動䜜するずいう事実は、そのような状況ではTypeScriptに頌るのが自然なようです。ノヌドサヌバヌのセットアップは非垞に高速で、通垞は䞍芁な䟝存関係はありたせん。これにより、システムリ゜ヌスが節玄されたす。これが、Node.jsずTypeScriptの匷力なタむプシステムの組み合わせが、新しい機胜をすぐに䜜成するのに非垞に効果的である理由です。



最埌に、TypeScriptは構文シュガヌで十分に味付けされおいるため、TypeScriptを䜿甚した開発は玠晎らしく高速です。



All Articles