Typescript: Kelas sebagian

Dibuat pada 29 Agu 2014  ·  224Komentar  ·  Sumber: microsoft/TypeScript

Tambahkan dukungan kelas parsial. Mixin tidak sama, karena ini adalah realisasi run-time. Perlu realisasi kompilasi, di mana sebagian kelas akan digabungkan menjadi satu sebelum mengkonversi TypeScript ke javascript.

//FileA.ts
partial class ClassA
{      
    constructor(public name: string) {}
    public sayHello(): string { return "hi!"; }
}

//FileB.ts
partial class ClassA
{
   public sayBye(): string { return "by!"; }
}

akan:

partial class ClassA
{      
    constructor(public name: string) {}
    public sayHello(): string { return "hi!"; }
    public sayBye(): string { return "by!"; }
}
Out of Scope Suggestion

Komentar yang paling membantu

Kasus penggunaan untuk kelas parsial adalah untuk kelas proxy yang dihasilkan. Misalnya pembungkus WebAPI atau SignalR. Akan sangat menyenangkan untuk dapat memperluas kelas proxy yang dihasilkan dengan logika khusus. Terutama saat membuat kelas untuk model, akan menyenangkan jika dapat melampirkan logika bisnis langsung ke kelas model yang dikembalikan dari api.

Semua 224 komentar

Saya pikir Anda menggunakan "sebagian" pada modul juga dan membantu menyelesaikan masalah yang diangkat di sini.

https://github.com/Microsoft/TypeScript/issues/447

@disshishkov mungkin metode ekstensi sudah cukup : #9

Situasi seperti apa yang ingin Anda gunakan untuk ini, dan bagaimana solusi yang ada tidak memenuhinya?

Perhatikan bahwa ini diterapkan dalam C# untuk mendukung skenario pengeditan tipe WinForms di mana Anda memiliki file yang dibuat secara otomatis dan file yang diedit pengguna yang berkontribusi pada tipe yang sama; Saya tidak yakin situasi seperti itu berlaku di JavaScript/TypeScript.

Beberapa kelas dapat memiliki banyak nomor baris, hanya untuk pembacaan yang lebih baik, pemisahan ke beberapa kelas terpisah akan membantu. Anda dapat membagi berdasarkan jenis yang berbeda, misalnya dengan logika (jika logika ini tidak dapat dipindahkan ke kelas lain), dengan visibilitas (pribadi dan publik) dan lainnya. Dalam kasus ketika menyisir kelas parsial dapat memiliki masalah (misalnya 2 kelas parsial sama dengan metode/deklarasi variabel yang sama) kompiler harus memberi tahu dan membuang kesalahan.

Ini tidak terlalu menarik. Jika kelas Anda sangat besar sehingga tidak dapat diedit dengan nyaman dalam satu file karena ukurannya yang tipis, itu adalah bau desain yang sangat utama (misalnya komentar di http://programmers.stackexchange.com/questions/157482). Memisahkan berdasarkan tipe/logika/visibilitas/etc yang berbeda adalah sesuatu yang dapat ditangani oleh IDE atau oleh organisasi dalam satu file.

Sebaiknya diskusikan mengapa kelas Anda begitu besar sehingga tidak dapat dinavigasi (apakah karena alat navigasi harus lebih baik?), dan jika ada cara yang lebih baik agar bahasa dapat mendukung _decomposing_ kelas daripada hanya _splitting_ itu.

Secara pribadi, saya pikir "kelas parsial" harus ada, tetapi berperilaku seperti modul yang bergabung bersama. Saya memiliki sistem dengan modul yang, meskipun intellisense melihat semua modul (sebagaimana mestinya), JS aktual yang memuatnya hanya dimuat saat diperlukan. Saya pikir hal yang sama akan bagus untuk kelas juga - hanya memuat bagian yang diperlukan. Saya juga ingin membuat fungsi, dan menggunakan kelas untuk mengembangkannya lebih jauh. Saat ini, Anda hanya dapat melakukan ini dengan modul.

Kasus penggunaan untuk kelas parsial adalah untuk kelas proxy yang dihasilkan. Misalnya pembungkus WebAPI atau SignalR. Akan sangat menyenangkan untuk dapat memperluas kelas proxy yang dihasilkan dengan logika khusus. Terutama saat membuat kelas untuk model, akan menyenangkan jika dapat melampirkan logika bisnis langsung ke kelas model yang dikembalikan dari api.

+1 kvantestore.

Kasus penggunaannya persis sama dengan .net; sebagian dari kelas dihasilkan (dalam kasus kami, dari skema Avro) dan Anda ingin menambahkan kode pembantu tambahan untuk bekerja dengan kelas yang dihasilkan.

Saya suka saran ini. Saya ingin memiliki kelas parsial untuk memisahkan atribut/properti kelas yang membentuk "hierarki data" saya yang dapat dikumpulkan dalam satu file tunggal, dari metode mereka yang dapat dipecah menjadi beberapa file lain. Itu akan membuat kode lebih jelas dan lebih mudah dipahami dalam satu pandangan imo.

File hierarki data saya :

class A {
  x: number;
  y: number;
  z: number;
}

class B extends A {
  value: string;
  flag1: boolean;
  flag2: boolean;
}

File yang berisi metode kelas A :

class A {
  constructor(x: number, y: number, z: number) {
    this.x = x;
    this.y = y;
    this.z = z;
  }
  method1(...) { ... }
  ...
  methodN(...) { ... }
}

File yang berisi metode kelas B :

class B extends A {
  constructor(x: number, y: number, z: number, value: string) {
    super(x, y, z);
    this.value = value;
    this.flag1 = false;
    this.flag2 = false;
  }
  method1(...) { ... }
  ...
  methodN(...) { ... }
}

+1 dari saya. Saya ingin menggunakan templat tt untuk menghasilkan kelas TypeScript, tetapi menambahkannya dalam file terpisah yang tidak akan digantikan oleh pembuatan templat.

+1 Ini akan sangat membantu saya dengan kelas yang dibuat secara otomatis yang perlu saya perpanjang

Kelas Parsial sangat bagus tetapi tidak masuk akal untuk memilikinya. Ini menunjukkan Anda memiliki masalah desain. Aturan praktis dalam pemrograman adalah membuatnya tetap bodoh (KISS), terlepas dari bahasa yang Anda gunakan, adalah memecah kelas besar menjadi yang lebih kecil - dengan 1) memisahkan skrip ke dalam kelas dan memanggilnya (Kelas lain juga dapat menyebutnya kelas yang lebih kecil juga alih-alih menciptakan kembali roda), atau 2) pecah & diubah menjadi Abstrak/Antarmuka/Warisan/Virtual dll. atau polimorfisme.

Katakanlah Anda memiliki Kendaraan dengan segala isinya. Kelas parsial tidak masuk akal dan memperkenalkan kompleksitas & overhead di sini di mana lebih masuk akal untuk melakukan ini sebagai gantinya. Buat kelas Engine, kelas Tranny, kelas Drivetrain, kelas Pintu & kelas Ban sebagai kelas terpisah dan pindahkan skrip ke sana, yang ketika dipanggil masih dapat mendefinisikan Kendaraan di dalam kelas Kendaraan. Ini mengurangi skrip yang panjang & kompleksitas skrip. Kemungkinan Anda akan menemukan Anda memiliki skrip Pintu di sana-sini yang dapat disederhanakan dengan kelas Pintu. Interface/Abstract/Inheritance/Virtual dapat digunakan untuk mengubah definisi kelas Door pada beberapa skrip di kelas Vehicle.

Anda juga cenderung memiliki waktu pengembangan yang lebih sedikit dengan cara ini. Saya pernah memiliki ASP.NET C# Blog yang menggunakan banyak kelas parsial. Saya telah berjuang dengan itu karena terlalu banyak kelas parsial dan Anda tidak tahu di mana mereka berada. Ini seperti berurusan dengan logika GOTO dalam pemrograman. Buruk buruk!! Saya tidak pernah berhasil membuat tambalan untuk perbaikan bug, saya juga tidak dapat menyesuaikan skrip karena terlalu terkubur di tumpukan kelas parsial (begitu juga beberapa kata yang diganti namanya).

Hanya mengatakannya sebagai pemikiran 1 sen dari pikiranku.

@fletchsod-developer: Beberapa situasi ditangani dengan benar oleh pewarisan, tetapi tidak semua. Dan beberapa pengembang mungkin menyalahgunakan sebagian kelas, tetapi tidak semua. Ada beberapa situasi di mana saya menemukan kelas parsial sangat, sangat berguna, tetapi jika Anda tidak menyukainya, Anda tidak perlu menggunakannya.

@jfrank14 , seperti yang disarankan oleh @basarat di atas, apakah #9 tidak akan berfungsi untuk Anda?

// File1.ts
class Dog { 
 ...
}

// File2.ts
extends class Dog {
  woof() { /* ... */ }
}

@NoelAbrahams , apakah Anda dapat mengakses definisi dari file1 dalam file tetapi tidak sebaliknya? Tidak apa-apa bagi saya selama tidak tergantung pada urutan inklusi.

Saya sangat berharap kalian mempertimbangkan kelas parsial a la C# untuk TS... bagi saya satu-satunya alasan adalah pembuatan kode, yang merupakan alasan utama di balik kelas parsial C#... saat ini kami sedang melakukan banyak pembuatan kode TS, dan kami berharap untuk melakukan lebih dan lebih... saat ini kita harus mengandalkan "//

+1 - Benar-benar dapat menggunakan ini untuk menambahkan fungsionalitas ke kelas yang dibuat secara otomatis; tidak ada solusi elegan lain yang dapat saya pikirkan atau telah saya baca hingga saat ini ...

+1 - Kelas yang dihasilkan kode. Objek C#/Java diserialisasikan ke klien

Perlu ini juga untuk menggabungkan kelas yang dihasilkan!

Ini akan menjadi fitur yang sangat berguna untuk memungkinkan penggabungan sederhana dari kode yang dihasilkan dengan kode yang tidak dibuat.

+1

+1 - Kami juga membutuhkannya untuk kelas yang dihasilkan sebagian, akan lebih elegan daripada pewarisan yang memancarkan sedikit kode yang tidak diperlukan untuk tujuan ini.

+1

Mengalami batasan ini lagi - harap tambahkan fitur ini! :+1:

+1

+1

+1

+1

Orang-orang secara acak memberi +1 ini tidak akan melanjutkannya.

Kasus penggunaan sejauh ini adalah:

  • Saya memiliki kelas yang sangat besar yang menjangkau banyak file. @RyanCavanaugh menunjukkan bahwa kemungkinan besar masalah desain dengan kode yang kompleks dan tidak cukup untuk menjamin kompleksitas implementasi.
  • Itu seperti mereka.
  • Argumen lain tampaknya C # memilikinya.
  • Argumen lainnya adalah seputar kode yang dihasilkan dari bahasa lain.

Kasus penggunaan kedua dan ketiga tidak menarik dan yang keempat, saya menduga perlu beberapa tingkat menjelaskan bagaimana pengiriman #9 tidak akan memenuhi persyaratan yang sangat mirip dan bahkan Dekorator (#2249).

Sepertinya #9 akan menyelesaikan hal yang sama dan bahkan lebih umum (karena Anda dapat memperluas kelas selain kelas Anda sendiri). Tetapi mungkin masuk akal untuk menginginkan konten kelas dalam dua file (mungkin karena satu ditulis tangan dan yang lainnya dihasilkan oleh templat), dan untuk mengatakan bahwa kedua file mendefinisikan anggota penting kelas dengan kepentingan yang sama, dan tidak memerlukan yang satu itu. file "memperpanjang" kelas mendefinisikan yang lain.

Ini adalah perbedaan yang hampir ada, tetapi mungkin penting bagi sebagian orang dalam beberapa situasi.

Saya tidak ingin parsial pada kelas karena alasan yang disebutkan, tetapi pada modul masuk akal IMHO.

https://github.com/Microsoft/TypeScript/issues/447

Kelas parsial sangat berguna untuk kasus penggunaan khusus. Ini bukan pelanggaran pola OOP apa pun tetapi cara untuk mengatur dokumen kode, yang menyediakan:

  1. Kemampuan untuk membagi definisi kelas/tipe dalam beberapa file. Untuk file kode besar, ini adalah fitur rawatan ++.
  2. Peluang bagi compiler/build-system untuk menggunakan linkage bersyarat pada waktu kompilasi. Analogi MSBuild, kasus penggunaan konkret di C#: DBML, kelas desainer, dan bahkan hal-hal yang lebih mewah seperti https://github.com/dotnet/corefx/pull/2045/files.
  3. Perlindungan bawaan, sehingga dua (atau lebih) pengembang tidak bertemu satu sama lain selama check-in kode. Resolusi konflik meledak! :)
  4. Biarkan Anda membuat kode ke dalam kelas parsial utama, lalu membuat parsial lain untuk kelebihan beban khusus. Bekerja dengan sempurna!

Saya percaya dalam memisahkan logika bisnis dan lapisan data ke dalam kelas yang terpisah dan saya kebanyakan menggunakan metode statis di lapisan ini. Saya benar-benar tidak melihat bagaimana itu bisa menjadi lebih banyak kode dan kurang dapat dipelihara.

Sementara metode ekstensi adalah fitur bahasa inti yang dipengaruhi oleh pola OO dan akan diproses pada waktu kompilasi, sebagian kelas berhubungan dengan tata letak dokumen/kode untuk digabungkan pada tahap pra-kompilasi. Meskipun kesamaan dalam kelas parsial, kelas abstrak dan metode ekstensi, ada perbedaan yang jelas.

:+1: untuk membawa "Kelas Parsial" yang tidak berbahaya ke TypeScript.

Kasus penggunaan saya untuk kelas parsial adalah untuk pembuatan kode -- tim saya harus dapat membuat bagian kelas secara otomatis dalam satu file dan menambahkan metode dan properti khusus dengan tangan di file lain. Saya agak bingung mengapa @RyanCavanaugh "tidak yakin situasi seperti itu berlaku di JavaScript/TypeScript", karena kasus penggunaan ini tidak terkait dengan bahasa pilihan.

Baik dekorator maupun metode ekstensi tidak memecahkan masalah pembuatan kode seanggun kelas parsial, dan masing-masing memiliki kompleksitas tambahan yang substansial.

+1

+1

+1 untuk tujuan pembuatan kode.

Di lingkungan C#, integrasi transpiler kelas C# ke kelas TypeScript akan menghilangkan kebutuhan untuk menyimpan dua definisi kelas yang berbeda antara server dan sisi klien karena sisi klien, alias kelas TypeScript, akan dibuat secara otomatis dan sebagian kelas bahwa masalah ini meminta akan memungkinkan penyesuaian saat diperlukan saat masih berkembang di TypeScript asli.

+1 untuk skenario pembuatan kode

+1 sangat membantu untuk pembuatan kode

Mengapa tidak menggunakan warisan untuk pembuatan kode?

Warisan lebih berantakan dan memiliki lebih banyak overhead.

Pada Senin, 10 Agustus 2015, 10:09 Gorgi Kosev [email protected] menulis:

Mengapa tidak menggunakan warisan untuk pembuatan kode?


Balas email ini secara langsung atau lihat di GitHub
https://github.com/Microsoft/TypeScript/issues/563#issuecomment -129468291
.

Warisan menciptakan kopling nama yang tidak berguna

Warisan kurang mengagumkan karena:

  1. Memperdalam rantai prototipe yang tidak perlu dan memperlambat instantiasi,
    meskipun itu bukan masalah besar untuk sebagian besar aplikasi, kemungkinan semuanya kecuali game;
  2. Karena kurangnya abstrak dan menimpa baik kehilangan beberapa jenis keamanan atau
    memperkenalkan perlunya beberapa pola penghargaan seperti casting di antara keduanya
    jenis;
  3. Membingungkan secara keseluruhan karena memiliki kelas dasar mengomunikasikan gagasan bahwa
    itu dapat diperpanjang oleh kelas lain, yang jarang terjadi dengan codegen

Tidak mengatakan TypeScript HARUS memiliki kelas parsial untuk mendukung codegen, hanya
bahwa kelas parsial jauh lebih baik daripada warisan atau
komposisi.

@JoshMcCullough Inheritance overhead di JS minimal, dan saya tidak melihat bagaimana itu lebih berantakan daripada kelas parsial: dengan itu Anda berpotensi membagi kelas menjadi 10 file dan mengejar metode Anda di semua tempat.

@yahiko00 Apa jenis "penggabungan nama yang tidak berguna" yang kita bicarakan di sini? Apakah Anda merujuk pada hal-hal yang perlu Anda lakukan untuk mendapatkan No. 2 di bawah ini (mengkodekan nama kelas yang diperluas)?

@hdachev

  1. Ada beberapa overhead, tetapi cukup minimal - hanya terlihat jika Anda melakukan hal-hal yang menerjemahkan langsung ke beberapa instruksi mesin
  2. Poin bagus - Anda tidak mendapatkan kelas yang diperluas ketika Anda harus mereferensikan kelas yang dihasilkan dari kelas yang dihasilkan lainnya.
  3. Kelas-kelas itu memang dimaksudkan untuk diperpanjang - jika tidak, Anda dapat membuatnya dan menyelesaikannya, bukan?

AFAIK ini tidak ada di radar ES7+, bukan? Itu mungkin bermasalah...

Bagaimanapun, melampirkan hal-hal tambahan ke prototipe kelas yang ada cukup sepele dalam JavaScript dan sama sekali tidak biasa, jadi mungkin ide yang baik untuk memiliki sintaks untuk itu ...

Ini mudah di TS tetapi JS di belakang layar akan menggandakan
"protoyping" jika Anda menggunakan kelas dasar untuk semua data yang Anda hasilkan
objek. Mungkin bukan dampak kinerja yang serius kecuali Anda memiliki banyak
objek data, tetapi masih tidak perlu ketika kita tahu bahwa "sebagian"
kelas" dimungkinkan.

Pada Senin, 10 Agustus 2015 pukul 11:03 Gorgi Kosev [email protected]
menulis:

@JoshMcCullough https://github.com/JoshMcCullough Warisan overhead
di JS minimal, dan saya tidak melihat betapa berantakannya daripada kelas parsial:
dengan itu Anda berpotensi dapat membagi kelas menjadi 10 file dan mengejar Anda
metode di semua tempat.

@yahiko00 https://github.com/yahiko00 Apa jenis "nama tidak berguna
kopling" yang kita bicarakan di sini? Apakah Anda merujuk pada hal-hal yang Anda perlukan
lakukan untuk mendapatkan No. 2 di bawah ini (hardcode nama kelas yang diperluas)?

class MyClass memperluas GeneratedMyClass { ... }

@hdachev https://github.com/hdachev

1.

Ada beberapa overhead, tapi cukup minim
https://jsperf.com/prototype-chain-vs-direct-calls - hanya terlihat
jika Anda melakukan hal-hal yang menerjemahkan langsung ke beberapa mesin
instruksi
2.

Poin bagus - Anda tidak mendapatkan kelas tambahan ketika Anda harus
referensi kelas yang dihasilkan dari kelas yang dihasilkan lainnya.
3.

Kelas-kelas itu memang dimaksudkan untuk diperpanjang - jika tidak, Anda bisa
menghasilkan mereka dan dilakukan dengan itu, kan?

AFAIK ini tidak ada di radar ES7+, bukan?

Bagaimanapun, melampirkan hal-hal tambahan ke prototipe kelas yang ada
cukup sepele dalam JavaScript dan sama sekali tidak biasa, jadi mungkin a
ide bagus untuk memiliki sintaks untuk itu ...


Balas email ini secara langsung atau lihat di GitHub
https://github.com/Microsoft/TypeScript/issues/563#issuecomment -129483174
.

@Davidhanson90 file itu tidak memiliki kelas di dalamnya. Apakah Anda bermaksud memposting ini di utas yang berbeda?

Saya akan memposting ke utas yang benar. https://github.com/Microsoft/TypeScript/issues/447

+1

+1

+100

+1

+1

+1 untuk pembuatan kode.
Saya telah masuk ke angularjs dan webapi dan saya ingin membuat alat yang pada dasarnya membuat definisi JS otomatis dari objek dan layanan c # saya. Saya ingin kemudian dapat memperluas kelas-kelas ini tanpa harus mengedit definisi JS "perancah". Saya telah melihat bahwa beberapa orang lain meminta ini dan sepertinya kami memiliki kasus penggunaan yang serupa.

+1 untuk pembuatan kode

+1 untuk pembuatan kode, angular memiliki banyak kode boilerplate, kami sudah melakukan banyak pembuatannya, tetapi dengan kelas parsial kami akan dapat melakukan lebih banyak lagi.

+1 lagi untuk pembuatan kode. Mencoba memperluas kelas di file lain paling tidak berantakan.

@RyanCavanaugh , apa yang diperlukan untuk mengeluarkan ini dari mode "+1" dan bergerak ke arah yang produktif?

-1 sintaks berikut lebih baik untuk mixin: #2919

Tidak yakin mengapa kita tidak dapat memiliki kelas parsial dan mixin; dua fitur yang sama sekali tidak berhubungan.

+1

Ini akan menyenangkan ketika kode dibuat, tetapi Anda tidak ingin memodifikasinya untuk menambahkan sesuatu ke kode yang dihasilkan.

+1

Saya punya proposal yang harus memenuhi kedua kasus penggunaan ini:

  1. Anda ingin menulis metode kelas Anda sendiri di tempat yang berbeda.
  2. Anda ingin menambahkan metode baru ke kelas orang lain, misalnya builtin.

Untuk (2), biasanya Anda cukup menggunakan operator :: untuk mendapatkan sintaks infix.

Tetapi jika Anda ingin kelas lama menjadi bagian dari antarmuka baru, atau jika Anda ingin mengirim secara dinamis, Anda harus benar-benar memodifikasi prototipe.

interface ITimes {
    times(n: number): number
}

Array implements ITimes {
    times(n: number): number {
        return this.length * n
    }
}

// The compiler should check that all methods of ITimes and IOther are implemented.
Number implements ITimes, IOther {
    times(n: number): number {
        return this * n
    }

    other(): void {}
}

// The old types should typecheck with the new interface.
const x: ITimes = true ? [] : 0
x.times(3)

// The interface list can be empty. This essentially gives you partial classes.
MyClass implements {
    anotherMethod(): void {}
}

(Dalam contoh saya menggunakan nama metode string, tetapi karena ini adalah tipe bawaan, menggunakan simbol akan lebih baik setelah itu dapat diketik.)

Peningkatan yang dimiliki ini atas kelas parsial yang benar adalah bahwa kelas memiliki definisi tunggal, dan tempat lain hanya memperluasnya. Ini berarti ada tempat yang jelas untuk mengimpor kelas dan membuat terjemahan ke JS lebih mudah.

:+1: Saya juga ingin melihat kelas parsial.

Apa status fitur ini?

Kasus penggunaan ini misalnya:

Saya memiliki paket Math yang mendefinisikan kelas Set , dengan metode Set#add , 'Set#remove'

// math.ts
export partial class Set {
  add(){}
  remove(){}
}

Saya memiliki paket opsional , heavy , Relational yang mendefinisikan kelas Relation dan Tuple .

Paket Relational ini juga akan menambahkan metode Set#product .

// relational.ts
///<reference path="./../math/tsd.d.ts"/>
partial class Set {
  product(){}
}

export class Relation(){}
export class Tuple(){}

Kelas parsial akan memungkinkan saya untuk membuat kelas dengan cara yang lebih fleksibel. Jika saya tidak ingin menggunakan paket relational yang berat, saya masih dapat menggunakan fungsionalitas Set dasar. Kelas partial hanya akan masuk dan menambahkan fungsionalitas tambahan ke kelas.

Saya menggaruk-garuk kepala untuk melakukan sesuatu yang akan memiliki API yang bagus tanpa menggunakan sebagian dalam kasus ini.

Yang bisa saya dapatkan hanyalah beberapa pola repositori.

// Without partials

// base

export class Base {
    static registerOperation(opName, method){
        this.prototype[opName] = method;
    }
    operation(name, ...args){
        return this[name].apply(this, args);
    }
}

// math.ts
import {Base} from './base';
class Set extends Base{
    // Define the methods here
    add(){}
    remove(){}
}

// Or here
Set.registerOperation("add", function(...){});
Set.registerOperation("remove", function(...){});

// relational.ts
import {Set} from './../math/math';

Set.registerOperation("product", function(...){});

// app.ts

import {Set} from 'math';

var set = new Set();
set.add // compiler error
set.remove // compiler error
set.product // compiler error

// have to use something like
set.operation("add", args);
// or
(<any>set).add(arg);

+1 Saya menggunakan t4 untuk menghasilkan kelas dan proxy melalui WebApi. Saya pikir pembuatan otomatis banyak digunakan dalam TypeScript dan ketika menyangkut pembuatan otomatis, kelas parsial diperlukan!

Akan sangat bagus untuk memisahkan aspek dari kelas yang sama terutama di React
+1

+1 Pembuatan kode dan "Pemisahan yang cukup" dalam kasus objek data murni yang dapat digunakan kembali dengan atribut khusus klien untuk validasi seperti yang akan rapi untuk didefinisikan di kelas tetapi dipertahankan dalam bagian terpisah dari kode sumber.

+1 untuk Pembuatan kode kelas parsial dan kode tangan anggota tambahan untuk kelas-kelas ini dalam file terpisah.

+1

+1 Saya memiliki basis metode yang besar di layanan js api kami, akan lebih baik untuk membaginya menjadi file, yang membuatnya mudah untuk memahami setiap metode.

layanan api seperti fb (facebook) atau gq (google analytics) , di mana Anda diberikan satu kelas atau objek global, yang dapat Anda gunakan selama pengembangan Anda.

+1

Fitur ini akan menjadi nilai tambah yang besar bagi kami juga.

Kami mengembangkan middleware di mana semua jenis klien dapat terhubung, dan berkomunikasi dengan server kami melaluinya.

Kami menghasilkan beberapa kode klien berdasarkan apa yang diekspos oleh server.

Sejauh ini, semuanya baik-baik saja. Tapi sekarang, kami ingin dapat mentransfer koleksi objek yang heterogen (tetapi dengan kelas dasar yang sama). Objek yang ditransfer adalah bagian dari kode yang dihasilkan berdasarkan API server.

Untuk dapat menggunakan kekuatan pewarisan, metode abstrak adalah kuncinya dalam hal ini. Tetapi pengembang kami tidak akan menambahkan metode ke kode yang dihasilkan, saya kira semua orang tahu alasannya;)

Sejauh yang saya mengerti (saya seorang pengembang C #), solusi yang diusulkan di sini ( https://github.com/Microsoft/TypeScript/issues/9 ) tidak akan memungkinkan kami melakukan itu.

Jadi, kelas parsial akan sempurna bagi kami. Kami akan menghasilkan kelas sebagai parsial, dan jika pengembang perlu menambahkan logika atau metode, mereka hanya perlu menulis bagian lain di mana pun mereka mau.

+1

+1 sangat membantu untuk pembuatan kode

Saya ingin tahu apakah augmentasi modul pada dasarnya meniadakan kebutuhan untuk ini sebagai fitur khusus.

Jika Anda memiliki kelas yang dihasilkan maka Anda harus dapat melakukan sesuatu seperti ...

import {MyClass} from "./MyClass.generated"

MyClass.prototype.partialMethod1 = function() {
  return true;
}
MyClass.prototype.partialMethod2 = function(abc: string) {
  this.doSomething(abc);
}

declare module './MyClass.generated' {
  interface MyClass {
    partialMethod1(): boolean;
    partialMethod2(abc: string): void;
  }
}

@disshishkov Itu sepertinya cara yang baik untuk mengimplementasikannya di bawah penutup, tapi saya masih ingin dukungan kelas satu yang tepat dalam bahasa tersebut tanpa perlu memodifikasi prototipe secara manual dan memelihara antarmuka itu.

Saya setuju dengan Elephant-Vessel. Bagian yang dibuat secara manual dari kelas parsial harus digabungkan secara longgar (pada waktu desain di TS) mungkin dari bagian yang dihasilkan.

Saran oleh @david-driscoll berfungsi untuk banyak kasus. Namun, sejauh yang saya tahu, prototipe tidak memiliki akses ke variabel internal. Ini membatasi kegunaan pendekatan ini dalam konteks pembuatan kode di mana Anda ingin membuat bagian inti dari kelas Anda dan kemudian menambahkannya dengan kode khusus.

+1

@david-driscoll yang terlihat seperti cara terbaik untuk menghilangkan fitur ini. (perlu menambahkan kemampuan untuk mengakses properti pribadi/dilindungi). Ingin tahu apa yang akan terjadi dengan beberapa deklarasi kelas parsial? Apa yang akan menjadi visibilitas timbal balik dari mereka?

++ 1 Kurangnya sebagian benar-benar menyakiti saya ketika mencoba memperluas model yang dibuat secara otomatis..

Saya pikir satu-satunya hal dalam ruang lingkup di sini pada dasarnya adalah apa yang diusulkan @david-driscoll -- Anda dapat mendeklarasikan metode baru (yang akan diletakkan pada prototipe) dan properti _non-inisialisasi_ baru (yang tidak memiliki codegen), tetapi bukan properti baru yang diinisialisasi (karena ini memiliki efek samping pada codegen konstruktor).

downvoted, maafkan bahasa Prancis saya, kelas parsial adalah upaya bodoh untuk memotong kelas dewa Anda, yang tidak dapat dihindari di OOP, menjadi beberapa file sehingga lebih mudah dikelola (walaupun masih menjadi kelas dewa)

dengan OOP tidak ada masa depan untuk kalian (pernah ke sana, tahu apa yang saya bicarakan)

datang ke FP, kami memiliki cookie dan cara untuk menulis program tanpa satu kelas dan s**t seperti ini

Jadi pada dasarnya kita sudah mengizinkan ini melalui interface A { method(): void } A.prototype.method = function() { }; ; mengkodifikasi ini menjadi gula untuk hal yang masuk akal.

Satu hal untuk bikeshed adalah kata kunci partial . Sebuah sketsa sejarah singkat: Dalam C#, partial class awalnya akan menjadi extension class (yang Anda masukkan pada semua kecuali satu deklarasi), tetapi tidak ada perbedaan yang jelas tentang deklarasi mana yang akan menjadi extension dan deklarasi mana yang akan menjadi deklarasi non-ekstensi. Sebagai gantinya Anda memiliki pengubah partial yang harus Anda tempatkan di kelas _all_.

Ini adalah _not_ kasus di TypeScript; justru sebaliknya. Di sini, hanya satu kelas (sebut saja "deklarasi _primary_") yang mungkin memiliki konstruktor / bidang anggota yang diinisialisasi; deklarasi utama tidak mendapatkan pengubah baru. Setiap deklarasi lainnya (sebut saja "deklarasi _extension_") mungkin hanya memiliki statika, metode, dan bidang yang tidak diinisialisasi, dan Anda akan _perlu_ memiliki beberapa pengubah untuk menunjukkan bahwa itu bukan yang utama.

Tebakan terbaik saat ini adalah

class Foo {
  x = 6; // only legal to initialize here
  constructor() { } // only legal to have constructor here
  someMethod() { }
}

// vvvvvvvvv thoughts?
   extension class Foo {
     someOtherMethod() {
     }
   }

:berkilau: :sepeda: :rumah: :berkilau:

Bikeshedding atau tidak, ini terdengar mengerikan seperti #311 yang ditinggalkan karena kemungkinan mengganggu standar ECMAScript di masa depan. Mengapa ini layak dipertimbangkan, tetapi dukungan mixin yang tepat tidak?

Menggunakan kata kunci extension bertentangan dengan metode ekstensi ? Atau apakah ini akan meniadakan metode ekstensi sepenuhnya?

@kitsonk Saya pikir proposal mixin memiliki lebih banyak pertanyaan terbuka. Proposal kelas parsial di sini hanyalah kodifikasi dari hal-hal yang sudah diizinkan di TypeScript, hanya dengan beberapa gula sintaksis (fitur ini benar-benar dapat dilakukan sebagai pemetaan ulang sintaksis untuk hal-hal yang sudah kita miliki).

@Elephant-Vessel Saya tidak berpikir metode ekstensi terjadi jika sebagian kelas terjadi. Kelas adalah satu-satunya tempat di mana metode ekstensi masuk akal mengingat batasan kami, dan operator pengikatan ES7+ yang diusulkan adalah cara yang lebih baik untuk menyesuaikan sintaksis seperti ekstensi.

@RyanCavanaugh : bagi saya, sepertinya agak membatasi untuk mengharuskan satu kelas utama dan yang lain tidak. Jika Anda ingin mempartisi kode Anda sehingga satu file berisi semua metode kelas dan yang lainnya berisi semua properti, tidak ada yang tampak lebih primer, dan mengapa Anda harus dipaksa untuk memilih? Bukankah lebih bersih untuk memiliki sebagian di mana semuanya sama pentingnya, dan digabungkan oleh kompiler?

@RyanCavanaugh ... Saya akan melakukannya dengan cara yang persis sama dengan c# melakukannya ... ini berfungsi dengan baik untuk pembuatan kode ... yang saya yakini adalah masalah utama fitur yang dimaksudkan untuk diselesaikan di c # ... meskipun memori saya kabur ... tidak pernah ada masalah, sudah ada selama bertahun-tahun, dan diuji dalam pertempuran...

Jika kelas parsial/diperpanjang tidak akan dapat memiliki bidang yang diinisialisasi, saya pikir akan lebih rapi untuk mendukung sesuatu seperti metode parsial yang kita ketahui dari C# , pada dasarnya kontrak ringan khusus untuk kelas parsial. Jadi seperti:

public partial class MyGeneratedClass
 {
     partial void Initialize();
     public constructor()
     {
          //...
         this.Initialize();
    }
 }

 public partial class MyGeneratedClass
 {
     partial void Initialize()  { //... }
 }

Kebutuhan untuk dapat memilah/memperluas kelas pihak ketiga dapat dengan mudah(?) diselesaikan dengan membuat partial/extends umumnya opsional tetapi diperlukan untuk penggunaan metode parsial.

Saya pikir ini bisa membawa beberapa kekuatan ekspresif dan operatif yang rapi ke konsep yang kita inginkan di sini.

Mereka yang mencari mixin.

Pertimbangkan objek menginisialisasi proposal yang dengannya (dan analisis aliran) mixin dapat dilakukan dengan elegan, alami, idiomatik sejauh JavaScript berjalan:

function enableBeingPositioned<a>(
   // hypothetical syntax
   something: a /* <-- before type */ => a & { x: number; y: number; } /* <-- after type */
): void { 
   something.x = 0;
   something.y = 0;
}
let value = {};
value.x; // <-- should not typecheck
enableBeingPositioned(value);
value.x; // <-- should typecheck

Bahasa seperti Java tidak menawarkan kelas/struktur parsial. Ini adalah fitur khusus dari C#. Meniru konsep C# "partial class/struct" sepenuhnya adalah cara terbaik untuk pergi ke sini.
Pada langkah pra-kompilasi, hal pertama yang dapat dilakukan oleh kompiler TS adalah menjahit blok kode parsial dalam memori dan kemudian beralih ke rute pipa kompilasi reguler. Ini akan lebih dari cukup untuk memenuhi syarat v1.0.0-preview1.0000 dari fitur Kelas Parsial di TypeScript.
Apa pun di luar apa yang ditawarkan C# adalah sesuatu yang dapat diperkenalkan di versi yang lebih baru ketika fitur tersebut akan berkembang dan hidup lebih lama dari uji coba/pratinjaunya. Kasus sudut dan hal-hal serupa yang tidak jelas dapat didiskusikan secara terpisah satu per satu dan kita dapat khawatir tentang fit&selesainya nanti... IMO.

Saya juga setuju melakukan kelas parsial dan ekstensi persis seperti c#
apakah itu cara terbaik untuk pergi dalam hal sintaks dan semantik, keduanya berfungsi
sangat baik untuk kasus penggunaan masing-masing. Kelas parsial meningkatkan
kegunaan dari kode yang dihasilkan. Metode ekstensi meningkatkan kegunaan
metode statis yang beroperasi pada antarmuka, generik tertentu dan ketiga
jenis pesta. Keduanya sangat keren, tapi tolong ingat mereka bukan
fitur yang sama, saya mengatakan ini di sini karena sintaks yang diusulkan di atas.

Metode ekstensi akan memungkinkan seseorang untuk melakukan ini (maaf tentang kurangnya pemformatan,
mengetik di telepon):

memperpanjang MyType[] {
somethingSpecificToMyType() { ... }
}

perluas struktur WeirdThirdPartyData{
sama disini() { ... }
}

Itu antara lain seperti bisa menggunakan lib seperti garis bawah
tanpa cruft, yang pada dasarnya berarti menuai manfaat sintaksis dari
memperluas tipe bawaan tanpa benar-benar mencemari mereka.

Sangat singkat - mari kita tidak memperlakukan keduanya sebagai satu dan sama, keduanya sangat
keren tapi tidak sama. Saya pribadi ingin memiliki keduanya di kami
bahasa.

Ngomong-ngomong, sebagai catatan tambahan, saya membayangkan banyak orang merasa ngeri dengan gagasan
pembuatan kode dan siap menjelaskan kepada semua orang bahwa itu tidak memiliki tempat
dalam javascript karena ada lebih banyak cara idiomatis untuk mencapai hal yang sama.
Ada dua cara di mana pembuatan kode sangat membantu dalam beberapa hal:
proyek, seperti yang sedang saya kerjakan sekarang.

  • Dalam proyek yang sensitif terhadap kinerja, seperti game, di mana Anda baru saja melakukannya
    segalanya untuk memaksimalkan anggaran cpu Anda dengan pekerjaan yang bermanfaat, codegen sangat membantu
    untuk menghasilkan kode yang sederhana untuk dipikirkan dan sangat dapat dioptimalkan
    / kode monomorfik yang sangat baik. Misalnya, dalam
    mesin permainan entitas/komponen, kode yang dihasilkan dapat membantu banyak hal
    seperti kode boilerplate yang sangat cepat untuk menyatukan komponen, acara
    pengiriman, dll.
  • Di aplikasi bisnis besar, kode yang dihasilkan membantu mendapatkan jarak tempuh yang ekstrem
    sistem tipe, misalnya dengan memancarkan metode dengan sangat spesifik
    tanda tangan untuk kueri basis data, dll, yang memaksimalkan waktu kompilasi
    cek, membantu banyak dengan refactoring dan juga sangat menyederhanakan debugging
    karena memungkinkan Anda untuk melangkah melalui kode orkestrasi yang sangat sederhana.
  • Yang besar adalah ketika Anda menjaga beberapa komponen tetap sinkron
    beberapa lingkungan bahasa, misalnya sesuatu yang berhubungan dengan perpesanan
    seperti buffer protokol, atau hanya antarmuka pesan json, dll.

Sebagai simpul samping lain untuk kepentingan siapa pun yang bertanya-tanya apa sebagian
kelas ada hubungannya dengan codegen, nilai menjaga bagian yang dihasilkan
kelas menjadi file terpisah berasal dari persyaratan kontrol sumber -
barang yang dihasilkan biasanya merupakan artefak bangunan yang berubah dengan cepat dan Anda
tidak ingin itu dilakukan dalam repo Anda.

Saya suka ide untuk mengimplementasikan ini sesuai dengan model konsep ini yang terkenal dan dicoba, seperti yang dimiliki C#. 'Imitasi' memiliki beberapa konotasi negatif, tetapi memiliki nilai signifikan jika dilakukan dengan cerdas. Di sisi lain, bagian 'cerdas' dari itu adalah menyadari keadaan dan batasan yang berbeda, jadi saya tidak akan memprotes jika parsial untuk TypeScript tidak persis seperti parsial untuk C#.

@Elephant-Vessel, saya setuju bahwa itu tidak perlu salinan parsial C #, desain umum dapat ditata terlebih dahulu dibuat di sekitar rasa TypeScript / JavaScript sambil mengambil inspirasi maksimal dari C# parsial. Saran saya adalah menggunakan 'mendaftarkan kata kunci partial ' dan 'menjahit sebagian' sebagai langkah pertama, dan mengirimkannya sebagai fitur eksperimental/pratinjau (jadi konsumen tidak mulai bergantung padanya dalam kode produksi dengan benar dari kelelawar). Kemudian, berdasarkan respons komunitas, kembangkan fitur tersebut hingga siap diproduksi dan RTM. Jika kita khawatir tentang semua jenis gotcha dan skenario rumit sebelumnya, maka kemungkinan besar itu akan menunda masalah lebih lanjut.

+1 - Untuk memperluas dan memelihara objek yang dihasilkan.

+1 untuk mempertahankan kode yang dihasilkan

Saya membuat polyfill dan membagi kelas besar saya.

Mendefinisikan kelas sebagai antarmuka.

export class C {
  constructor() {
  }
}
export interface C {
  m(): void;
}

Menerapkan anggota kelas.

export default class extends C {
  m(): void {
  }
}

Gabungkan implementasi.

import {C} from './core';
import m from './member/m';

compose(C, m);
export {C}
import {assign} from './assign';
import {concat} from './concat';

export function compose<T extends new (...args: any[]) => any>(target: T, ...sources: T[]): T {
  return concat([target], sources)
    .reduce((b, d) => {
      void assign(b.prototype, d.prototype);
      for (const p in d) if (d.hasOwnProperty(p)) b[p] = d[p];
      return b;
    });
}

https://github.com/falsandtru/spica/commit/a6ff30da5319db5f25f703a29da48fc0f7dbe2fe

Saya pikir ini adalah ide yang buruk untuk satu alasan tertentu: itu akan membuat aturan yang sudah rumit untuk global, ambient, eksternal, namespaced, dan deklarasi rapuh masalah pewarisan tergantung urutan secara signifikan lebih buruk. Ini bukan C# dan resolusi nama dan deklarasi anggota sangat berbeda.

Mungkin gunakan objek atau namespace alih-alih kelas, ala pola modul yang mengungkapkan jika Anda benar-benar perlu melakukan ini. Kalau tidak, kelas Anda mungkin terlalu besar.

Juga dekorator dapat digunakan untuk mengimplementasikan asosiasi antara kode yang dihasilkan dan kode tulisan tangan.

Apakah Anda punya solusi lain?

Saya akan senang melihat ini ditambahkan ke TS juga

+1 untuk tujuan pembuatan kode (DTO dari referensi layanan WCF dengan definisi kelas parsial tambahan)

+1 untuk tujuan pembuatan kode. Kasus penggunaan saya adalah: Saya memiliki komponen React yang fungsi render() dihasilkan secara eksternal melalui react-templates .

Dengan kelas partial saya bisa mengetik-memeriksa fungsi tersebut versus kelas utama ( Component ). Tanpa kelas parsial, satu-satunya hal yang bisa saya lakukan adalah mengikat fungsi ke kelas utama dan berharap yang terbaik.

Dengan TS 2.0 berikutnya, saya berpikir bahwa beberapa kasus pembuatan kode mungkin ditutupi dengan fitur tipe this .

Misalnya dalam kasus yang saya jelaskan sebelumnya, alih-alih

partial class MyComponent extends React.Component<any,any> {
    render() {
        ...
    }
}

Saya bisa menulis

function render<this extends MyComponent>()
        ...
}
MyComponent.prototype.render = render;

+1 Sebagai pengembang, saya ingin kelas parsial sehingga banyak templat dapat menghasilkan/memodifikasi kelas yang sama yang tersebar di banyak file.

Komentar saya secara khusus berkaitan dengan kelas parsial, bukan untuk mixin. Keduanya pada dasarnya berbeda. Kelas parsial adalah tentang memecah kode fisik, mixin adalah tentang memecah perilaku logis menjadi sifat-sifat yang dapat digunakan kembali yang memperkaya objek lain pada jenis dan tingkat nilai.
Saya tidak berpikir kelas parsial adalah ide yang baik untuk TypeScript. Mixin, di sisi lain adalah ide yang bagus, memberikan peningkatan ekspresi dan penyatuan yang sangat baik dengan sistem tipe TypeScript dan idiom JavaScript seperti yang ditunjukkan oleh @aleksey-bykov

@wendellm dapatkah Anda memikirkan cara yang bersih untuk melakukan ini mengingat Modul ES bersifat fisik. Kelas parsial bekerja dengan baik dan sangat masuk akal dalam bahasa seperti C# di mana modul logis bukan fisik. Dari sudut pandang CLR, ruang nama tidak ada, hanya saja nama kelas dapat memiliki titik di dalamnya (sumber wawancara dengan @ahejlsberg)

+1 Saya butuh kelas parsial!

bisakah kita ekstensi antarmuka? antarmuka juga dapat memiliki beberapa fungsi yang diimplementasikan, seperti Swift:

interface Rect {
    x: number
    y: number
}

extension Rect {
    area() => this.x * this.y
}

Versi cepat:

protocol Rect {
    var x: Float {get}
    var y: Float {get}
}
extension Rect {
    func area() -> Float {
        return self.x * self.y
    }
}

+1

Pembuatan kode dan kelas parsial berjalan beriringan.

Warisan adalah solusi yang buruk untuk apa yang pada dasarnya adalah arahan #include dimuliakan.

Ambil Angular 2 misalnya. Itu tidak akan membaca metadata dari kelas induk, membuat ekstensi-oleh-warisan tidak praktis.

@tsvetomir itu masalah Angular bukan masalah TypeScript.

Warisan adalah solusi yang buruk untuk apa yang pada dasarnya adalah arahan #include yang dimuliakan

Ya warisan adalah solusi yang buruk, tetapi masalahnya adalah menggunakan kelas di tempat pertama. Mereka memiliki tempat mereka tetapi sangat terbatas. Kelas JavaScript cukup lemah dan tidak ekspresif dibandingkan dengan kelas dalam bahasa lain.

TypeScript bukan bahasa "Sudut"... Tidak pernah

Pada 23 Juli 2016, pukul 21:46, Aluan Haddad < [email protected] [email protected] > menulis:

@tsvet omirhttps://github.com/tsvetomir itu masalah Angular bukan masalah TypeScript.

Warisan adalah solusi yang buruk untuk apa yang pada dasarnya adalah arahan #include yang dimuliakan

Ya warisan adalah solusi yang buruk, tetapi masalahnya adalah menggunakan kelas di tempat pertama. Mereka memiliki tempat mereka tetapi sangat terbatas. Kelas JavaScript cukup lemah dan tidak ekspresif dibandingkan dengan kelas dalam bahasa lain.

Anda menerima ini karena Anda berkomentar.
Balas email ini secara langsung, lihat di Gi tHubhttps://github.com/Microsoft/TypeScript/issues/563#issuecomment -234753589, atau bisukan pembacaannyahttps://github.com/notifications/unsubscribe-auth/AJPCIh7n2_0dt00kw- XJv7tc9LB0tPsIks5qYtH4gaJpZM4CcixK.

Saya tidak melihat masalah ini sebagai spesifik Angular dengan cara apa pun. Ini adalah kasus khusus di mana sebagian kelas mungkin telah membantu.

Permintaan berasal dari pengalaman masa lalu dengan C# dan kurangnya fitur yang familiar. Perbandingan tidak dapat dihindari karena TypeScript tidak berusaha untuk menjauhkan diri dari .NET. Beberapa bentuk paritas fitur diharapkan oleh penggunanya.

Permintaan berasal dari pengalaman masa lalu dengan C# dan kurangnya fitur yang familiar. Perbandingan tidak dapat dihindari karena TypeScript tidak berusaha untuk menjauhkan diri dari .NET. Beberapa bentuk paritas fitur diharapkan oleh penggunanya.

@tsvetomir sebagai pengembang .NET lama, dan sebagai programmer C# yang bersemangat, pada dasarnya saya tidak setuju.

Artikel yang Anda kutip tidak otoritatif, dan tidak mencerminkan materi resmi apa pun dari tim TypeScript.

Selain itu, secara langsung bertentangan dengan filosofi desain TypeScript seperti yang dinyatakan oleh @ahejlsberg dalam berbagai pembicaraan, wawancara, dan posting.

Selain itu, sudut pandang artikel yang dikutip mencerminkan kesalahpahaman mendasar tentang sifat TypeScript.
Ironisnya, kesamaan yang dimiliki C# dengan TypeScript sebenarnya sama dengan JavaScript.
Kesamaan ini bukan pemrograman berbasis kelas, melainkan konstruksi seperti penutupan dan fungsi tingkat tinggi.

C# atau tidak, kita membutuhkan kelas parsial yang akan membantu TypeScript mendekati fitur prototipe Javascript.

@yahiko00
TypeScript sudah memiliki semua fitur prototipe JavaScript.
Ini adalah superset.

Ada beberapa masalah dengan gagasan kelas parsial di TypeScript, termasuk:

  1. Tidak seperti C#, definisi kelas TypeScript (JavaScript) bersifat imperatif bukan deklaratif. Mereka tampak deklaratif, tetapi sebenarnya tidak. Ini berarti mereka bergantung pada urutan eksekusi deterministik.
  2. Sistem modul ECMAScript didasarkan pada pengimporan unit kode fisik bukan logika.
    Misalnya, katakanlah saya punya

_app/kelas-saya-bagian-1.ts_

TypeScript export partial class MyClass { firstName = "John"; lastName = "Smith"; }

dan
_app/kelas-saya-bagian-2.ts_

TypeScript export partial class MyClass { fullName = this.firstName + ' ' + this.lastName; }

Bagaimana saya bisa mengimpor kelas ini? Karena saya tidak dapat mengimpor dari salah satu modul, mari kita bayangkan abstraksi hipotetis dalam TypeScript yang memungkinkan saya untuk menulis
_app/main.ts_

TypeScript import { MyClass } from './my-class';

Apa artinya ini? Bahkan jika kompiler TypeScript dapat menyimpulkan bahwa _app/my-class-part-1.ts_ harus dimuat sebelum _app/my-class-part-2.ts_, itu tidak dapat membuat pengimporan masing-masing bagian tidak valid juga tidak dapat memastikan mereka diimpor dalam urutan yang benar oleh pemuat modul asinkron seperti RequireJS atau apa yang pada akhirnya akan diimplementasikan di browser.

Seluruh gagasan kelas parsial pada dasarnya bertentangan dengan sistem modul ECMAScript.

Pembaruan: Itu perlu melakukan inferensi ketergantungan kompleks yang sewenang-wenang dan memancarkan beberapa JavaScript yang sangat aneh.

TypeScript sudah memiliki semua fitur prototipe JavaScript.
Ini adalah superset.

Saya seharusnya mengekspresikan diri saya lebih baik. Tentu saja kita semua tahu TypeScript adalah superset dari JavaScript. Tetapi saya ingin mengatakan bahwa kelas parsial akan membantu kelas TypeScript untuk lebih dekat dengan prototipe JS. Untuk saat ini, kita hanya dapat memiliki kelas "statis" dan tidak dapat diperpanjang, sedangkan, dengan pendekatan prototipe, kita dapat memperluas fungsi seperti kelas.

Mengimpor sebagian kelas akan mengarah pada perluasan sintaks ES6 saat ini yang saya setujui. Kita bisa membayangkan sesuatu seperti ini:

import { MyClass } from ['app/my-class-part-1', 'app/my-class-part-2'];

Kelas TypeScript didasarkan pada kelas ECMAScript dan dengan demikian menderita kurangnya ekspresif yang terakhir. Pertimbangkan untuk menggunakan fungsi, modul, "ruang nama", atau objek biasa untuk mencapai apa yang Anda butuhkan.

Fungsi adalah apa yang ingin kita hindari dengan gagasan kelas.
Modul atau ruang nama membawa ekstensibilitas sederhana dan tidak memiliki ekspresi yang sama dengan kelas TypeScript. Selain itu, namespace atau modul tidak dapat dibuat instance-nya. Mereka tidak melayani tujuan yang sama seperti kelas.

@aluanhaddad Saya mengerti maksud Anda tentang modul. Solusi yang mungkin adalah mengizinkan hanya satu file ke export partial class sedangkan sisanya hanya berisi definisi partial class . Anda mengimpornya dari tempat yang diekspor. Dari contoh Anda:

_app/kelas-saya.ts_

export partial class MyClass {
    firstName = "John";
    lastName = "Smith";
}

_app/kelas-saya.part.ts_

partial class MyClass {
    get fullName(): string {
        return this.firstName + ' ' + this.lastName;
    }
}

_app/main.ts_

import { MyClass } from './my-class';

Apa yang hilang adalah sintaks untuk memberi tahu kompiler di mana menemukan bagian-bagiannya. Ini bukan masalah dengan C# di mana Anda memproses semua file sekaligus. Ini mungkin sintaks khusus, seperti yang digunakan untuk penggabungan deklarasi .

Itu tidak diperlukan untuk kelas parsial untuk mengizinkan definisi sewenang-wenang. Mereka dapat dibatasi hanya untuk metode, properti dan konstruktor, misalnya. Ini membuat perintah eksekusi menjadi tidak signifikan dan memungkinkan kompiler untuk membuat kesalahan jika anggota diduplikasi.

Saya gagal melihat mengapa Modul Augmentasi tidak valid untuk skenario ini. Ini bekerja sangat baik bagi kami dengan Rxjs5.

Anda cukup membuat kelas dasar Anda, dan kemudian dengan pembuatan kode Anda, buat semua metode tambahan yang Anda butuhkan di atas kelas dasar. Tidak masalah jika kode yang dihasilkan cantik, tidak ada manusia yang seharusnya menulisnya.

Apakah ini pengganti yang sempurna untuk kelas parsial? Saya kira tidak, tetapi saya tidak melihat kelas parsial terjadi kecuali ECMAScript memutuskan JavaScript membutuhkannya. Semantik tentang bagaimana sebagian kelas dihubungkan bersama antara modul eksternal saja membuat saya sakit kepala.

@david-driscoll untuk membuatnya lebih baik, metode yang ditambahkan dapat memiliki argumen this: dideklarasikan, untuk pemeriksaan tipe yang lebih kuat.

Dalam contoh yang dikutip dari Modul Augmentation :

// observable.ts stays the same
// map.ts
import { Observable } from "./observable";
declare module "./observable" {
    interface Observable<T> {
        map<U>(f: (x: T) => U): Observable<U>;
    }
}
Observable.prototype.map = function (this: Observable, f) {
    // here "this" has the shape of the "Observable" class
}

Ya. Rxjs belum tenang menggunakannya, karena fitur 2.0, dan 2.0 belum dirilis. Itu ada di daftar sasaran saya nanti.

Saya mengerti apa yang Anda maksud tentang modul. Solusi yang mungkin adalah mengizinkan hanya satu file untuk mengekspor sebagian kelas sementara sisanya hanya berisi sebagian definisi kelas. Anda mengimpornya dari tempat yang diekspor. Dari contoh Anda:

_app/kelas-saya.ts_

export partial class MyClass {
    firstName = "John";
    lastName = "Smith";
}

app/kelas-saya.part.ts

partial class MyClass {
    get fullName(): string {
        return this.firstName + ' ' + this.lastName;
    }
}

Saya suka konsep sintaksis tetapi masalahnya adalah Anda baru saja memperkenalkan _kind_ file sumber baru yang digunakan sebagai semacam modul implisit, terlihat seperti skrip, dan harus dimuat dengan cara tertentu.

Apa yang hilang adalah sintaks untuk memberi tahu kompiler di mana menemukan bagian-bagiannya. Ini bukan masalah dengan C# di mana Anda memproses semua file sekaligus. Ini mungkin sintaks khusus, seperti yang digunakan untuk penggabungan deklarasi.

Penggabungan deklarasi berfungsi untuk _declarations_, bukan file sumber.

Itu tidak diperlukan untuk kelas parsial untuk mengizinkan definisi sewenang-wenang. Mereka dapat dibatasi hanya untuk metode, properti dan konstruktor, misalnya. Ini membuat perintah eksekusi menjadi tidak signifikan dan memungkinkan kompiler untuk membuat kesalahan jika anggota diduplikasi.

Semua _are_ ini biasanya bergantung pada pesanan.

Sunting: Artinya, mendefinisikan mereka mengubah kelas.

Mungkin seseorang sudah menyebutkan ini, tetapi kasus berguna lainnya adalah ketika Anda membuat bagian dari kelas dari beberapa pembuat kode, maka Anda ingin menambahkan beberapa kode lagi secara manual secara langsung dalam implementasi Anda.
Anda tidak benar-benar ingin melakukan pencampuran atau kelas turunan.
Itu masih satu kelas - hanya sebagian yang dihasilkan secara otomatis bagian lain secara manual.

BTW: jika seseorang perlu membuat tipe TS dari kelas C #, Anda dapat memeriksa TypeScriptBuilder

Terima kasih telah mempertimbangkan ini!

Saya akan mencoba TypeScriptBuilder Anda ;)

Saran saya...

Bagaimana jika kompiler tidak mencoba menemukan semua bagian? Bagaimana jika saya harus mengimpor bagian lain dan mengendalikan semuanya?

/MyClass.partial.ts

export partial class MyClass {
    firstName = "John";
    lastName = "Smith";
}

MyClass.ts

// v- this would NOT throw an error because the definition is marked as partial
import { MyClass } from "./MyClass.partial";

export class MyClass {
    get fullName(): string {
        return this.firstName + ' ' + this.lastName;
    }
}

Kemudian...

  1. Jika saya ingin menggunakan MyClass saya harus mengimpornya dari MyClass.ts
  2. Saat dikompilasi, MyClass.partial.ts akan menghasilkan javascript yang memanjang MyClass.prototype seperti yang ditunjukkan di sini sebelumnya. Tapi itu mengekspor fungsi yang menerima prototipe untuk diperpanjang.
  3. MyClass.partial.ts diimpor ke MyClass setelah MyClass didefinisikan dan fungsi perluasannya dipanggil.

Di samping catatan ... tidak ada yang mencegah saya menghasilkan kode yang dikompilasi secara langsung. Tapi saya kehilangan semua kehebatan TypeScript.

@svallory Saya pikir itu pasti pendekatan yang tepat di sini. Khususnya karena Anda mengatakan kode yang dihasilkan akan mengekspor fungsi yang akan menyebabkan augmentasi, itu akan bekerja bahkan dengan impor asinkron karena fungsi dapat dipanggil dalam urutan deterministik yang diperlukan.

Secara lebih umum, dan saya lupa masalah di mana itu dirujuk, jika tugas ke prototipe kelas memengaruhi bentuk kelas, mungkin ada banyak manfaat. Ini akan meningkatkan perpustakaan mixin, membuat dekorator jauh lebih berguna, dan umumnya mendorong hierarki yang kurang vertikal.

Mungkin sulit bagi kompiler untuk melacak semua ini, tetapi mungkin bisa dibuat berfungsi dengan menjadi eksplisit seperti yang Anda sarankan.

Ini akan menjadi peningkatan pada sistem tipe, dengan kasus penggunaan kelas parsial keluar dari peningkatan itu.

Saya sudah melakukannya seperti berikut:

Saya sudah melakukannya seperti berikut :
 file1 . ts
 antarmuka ifoo {
 a ( ) : batal ;
 }
 kelas foo mengimplementasikan ifoo {
 a ( ) { /*melakukan sesuatu*/ }
 }
 berkas2 . ts
 /// <reference path="file1.ts" /> //tidak perlu
 antarmuka ifoo {
 b ( ) : batal ;
 }
 halo . prototipe . b = ( ) = > { /*melakukan sesuatu*/ }
 file3 . ts
 /// <reference path="file1.ts" /> //tidak perlu
 antarmuka ifoo {
 c ( ) : batal ;
 }
 ( < ifoo > foo . prototipe ) . c = ( ) = > { /*melakukan sesuatu*/ }
 konsumen . ts
 /// <path referensi="file1.ts" />
 /// <path referensi="file2.ts" />
 /// <path referensi="file3.ts" />
 misalkan f = foo baru ( ) ;
 f . sebuah ( ) ;
 f . b ( ) ;
 f . c ( ) ;

Augmentasi Modul masih menyelesaikan 90% masalah di sini. Diberikan contoh @svallory .

/MyClass.partial.ts

export partial class MyClass {
    firstName = "John";
    lastName = "Smith";
}

MyClass.ts

// v- this would NOT throw an error because the definition is marked as partial
import { MyClass } from "./MyClass.partial";

export class MyClass {
    get fullName(): string {
        return this.firstName + ' ' + this.lastName;
    }
}

Penambahan modul akan menjadi sesuatu seperti ...

MyClass.ts

export class MyClass {
    firstName = 'John';
    lastName = 'Smith';
}

MyClass.generated.ts

import { MyClass } from './test';

Object.defineProperty(MyClass.prototype, "fullName", {
    get(this:MyClass) {
        return this.firstName + ' ' + this.lastName;
    }
});

declare module './test' {
    interface MyClass {
        readonly fullName: string;
    }
}

Ini sedikit lebih bertele-tele daripada kelas parsial, tetapi sebenarnya kelas parsial hanya akan menjadi gula sintaksis untuk implementasi ini.

Satu-satunya gotcha hari ini yang tidak Anda miliki adalah:

  • Anda tidak dapat mengakses bidang pribadi atau terproteksi menggunakan sintaks this: MyClass .

    • Ini dapat dengan mudah diselesaikan dalam kode yang dihasilkan dengan mentransmisikan ke any .

    • Mungkin ini sesuatu yang dapat ditambahkan, sehingga Anda dapat mengakses anggota yang dilindungi this . Mungkin ada aturan lain di sekitar itu.

  • Kode yang dihasilkan terlihat sedikit lebih menakutkan , tetapi bagi konsumen, setelah hal-hal telah ditambah, mereka tidak akan pernah tahu bedanya.

EDIT: Perlu diingat, ini adalah sintaks TS 2.0+.

@david-driscoll saya setuju. Saya pikir itu lebih sederhana dan saya suka itu tidak memperkenalkan sintaks tambahan. Seperti yang Anda ketahui, saya menentang kelas parsial sebagai fitur bahasa tertentu, tetapi saya pikir akan bermanfaat jika TypeScript melacak penugasan ke prototipe secara umum dan menyempurnakan bentuk objek yang sesuai. Saya pikir pendekatan Anda adalah cara yang tepat untuk membagi kelas di beberapa file.

@wongchichong Contoh Anda menggunakan nama kelas global dan /// <reference path="..."/> . Saya tidak berpikir itu akan berskala dengan baik, meskipun Anda dapat menggunakan namespace untuk memperbaiki situasi.
Kode yang ditulis sebagai modul (yaitu modul eksternal) adalah binatang yang sangat berbeda karena melibatkan pemuat yang perlu mengetahui dependensi yang bergantung pada pesanan dan implisit. Itulah mengapa saran @svallory sangat berharga, ini membutuhkan jumlah kabel manual yang sangat minim yang membuat dependensi menjadi eksplisit.

Bagaimana jika seseorang tidak menggunakan modul?

@panklek kelas parsial masih merupakan ide yang buruk.

Untuk memperjelas, maksud saya mereka adalah ide yang buruk dalam bahasa seperti JavaScript di mana deklarasi kelas sangat penting, bukan deklaratif. Bahkan jika Anda menggunakan ruang nama, Anda akan berakhir dengan memecah kode Anda menjadi beberapa file yang berarti Anda harus bergantung pada urutan tag skrip dari file tersebut agar ini berfungsi sama sekali.

Dalam bahasa seperti C#, sebagian kelas bekerja dengan baik tetapi itu karena mereka pada dasarnya berbeda dari kelas dalam JavaScript.

Penting untuk diingat bahwa dalam JavaScript, deklarasi kelas bahkan tidak diangkat apalagi deklaratif.

Kecuali ES6, konsep "kelas" didefinisikan oleh TS. JS tidak memiliki gagasan tentang kelas _ sama sekali_.
Jadi terserah TypeScript untuk memutuskan seperti apa kelas itu, bukan?

Kecuali ES6,

Kami tidak dapat melarang ES6 saat membahas fitur bahasa TS, karena salah satu tujuan TS adalah mengikuti spesifikasi ES saat ini/yang akan datang .

Benar bahwa :/

Untuk sistem besar dengan kelas yang dihasilkan kode, yaitu Entitas, klien lapisan layanan, dll., kelas parsial sesuai dengan desain C#, memberikan solusi yang sangat elegan ketika kode yang dihasilkan perlu diperluas dengan status dan perilaku tambahan. Pada proyek saya saat ini, di mana kami memiliki ~500 kelas kode gen, saya sangat merindukan fitur ini.

Saya masih tidak mengerti mengapa beberapa orang begitu memusuhi fitur yang telah terbukti berguna di tempat lain, kecuali mengatakan "itu adalah ide yang buruk".

Sepertinya ini belum banyak dibahas di esdiscuss, satu-satunya utas yang saya temukan memiliki 9 posting.

@yahiko00 Bukannya saya memusuhi konsep tersebut. Seperti yang Anda katakan itu sangat berguna dalam bahasa seperti C#.

Sebagai programmer C# yang antusias, saya menemukan kelas parsial sangat membantu untuk tugas-tugas tertentu. Namun, mereka tidak mengganggu aspek lain dari bahasa. Mereka tidak merusak abstraksi terkait kunci seperti ruang nama, rakitan, dan deklarasi tipe yang dapat dipesan secara sewenang-wenang.

JavaScript, di sisi lain, memiliki sistem modul yang paling baru. Kelas adalah hal baru dan, menurut saya, belum terlalu ekspresif fitur bahasa, mereka perlu waktu untuk tumbuh.

Jika kita mengambil langkah mundur sejenak dan mempertimbangkan metode ekstensi, fitur lain yang kuat, dan jauh lebih berguna dari C#, saya akan senang melihat mereka ditambahkan ke JavaScript tetapi ada masalah mendasar dengan melakukannya yang belum diselesaikan.

Ketika kita mencapai titik di mana sebagian kelas dapat ditentukan tanpa merusak atau sangat membatasi konsep yang jauh lebih mendasar seperti modul, saya akan mendukung untuk menambahkannya.

Yang mengatakan, seperti yang ditunjukkan oleh @SaschaNaz , _does_ ini perlu ditangani dalam ECMAScript.

Mungkin ada yang berminat bisa buka thread baru di http://esdiscuss.org dan post urlnya disini biar kita bisa lanjut diskusi disana

PS: Atau di ES Discourse yang lebih mirip GitHub.
PS2: Atau di WICG juga-GitHub-like-and-more-active .

Saya juga ingin melihat beberapa konstruksi yang memungkinkan pembuatan kode untuk TS. Kelas parsial bekerja sangat baik untuk ini di C#.

Mungkin saya kehilangan sesuatu, tetapi menurut saya masalah intinya adalah memperluas kelas dengan akses ke variabel 'pribadi' dari tempat lain selain di konstruktor, lebih disukai dari file lain.

Berdasarkan diskusi, sepertinya banyak inovasi TS yang 'aman' telah dilakukan. Sekarang kami hanya menunggu untuk melihat apa yang dilakukan badan tata kelola ES karena kami tidak ingin merusak apa pun ke depan. Benar-benar valid, tetapi sedikit mengecewakan karena saya berharap kereta yang bergerak lebih cepat dengan TS.

Prasyarat adalah menemukan desugaring yang baik :

Meskipun sebelumnya saya pikir sebagian kelas cukup konyol karena Anda bisa menambahkan ke kelas secara langsung, saya dapat melihat daya tarik mengingat hal itu akan melibatkan membuat metode Anda tidak dapat dihitung plus memperbaiki ikatan super (yang terakhir saat ini tidak mungkin di ES6).

Pertama-tama kita perlu mencari tahu desguaring yang baik untuk kelas secara umum ke dalam komposisi, primitif imperatif, seperti toMethod yang lama. Tapi begitu kita memilikinya, menambahkan lebih banyak gula di atas seperti kelas parsial mungkin masuk akal, tergantung pada seberapa ergonomis --- atau tidak --- primitif itu akhirnya.

Tidak yakin apa artinya ini, tetapi mungkin seperti ini:

class A {
  foo() { return "foo" }
}
class B extends A {
}

partial(B, class {
  get foo() {
    return super.foo(); // should work
  }
});

(Cross diposting di esdiscuss )

Tampaknya ada cara yang cukup sederhana untuk mengimplementasikan kelas parsial dalam JS murni (dengan ES2017 getOwnPropertyDescriptors ). Orang ES mungkin berpikir bahwa gula sintaksis bahkan tidak diperlukan hanya untuk menghapus kode kecil ini.

function partial(base, extension) {
  extension.prototype.__proto__ = base.prototype.__proto__; // to enable 'super' reference
  const descriptors = Object.getOwnPropertyDescriptors(extension.prototype);
  delete descriptors.constructor; // must not override constructor
  Object.defineProperties(base.prototype, descriptors);
  
  return base;
}

Menggunakan ini di TS membutuhkan duplikat interface untuk memperluas tipe kelas yang ada, tentu saja.

@SaschaNaz Saya berharap properti yang ditambahkan ke konstruktor melalui getOwnPropertyDescriptors akan disembunyikan untuk IDE "sugesti otomatis" (karena ditambahkan saat runtime). Ingat, TypeScript lahir sebagai JavaScript dengan "autosugesti" (kadang orang menyebutnya "stronlgy typed" tapi sebenarnya yang mereka suka adalah "autosugesti").

PS Mengapa orang membutuhkan kelas parsial - pembuatan kode. Tetapi sekali lagi pembuatan kode harus didukung baik oleh IDE ("alat" mudah menyesuaikan ke file sumber, hasil hierarkis dalam file explorer, T4 atau dukungan "generator kode umum" serupa) dan dalam bahasa (kelas parsial, metode ekstensi). Hanya setelah memahami ini, menjadi mungkin untuk memahami apa yang sebenarnya ditanyakan oleh pengembang. Jika Anda tidak melihat gambaran lengkap - tentu saja "kelas parsial" terlihat seperti "omong kosong".

@aluanhaddad : tetapi bukankah fungsi utama TypeScript adalah memberi kami elemen bahasa yang tidak ada dalam JavaScript? Mengapa merupakan ide yang buruk untuk membagi kelas menjadi dua file TypeScript parsial, yang akan dikompilasi menjadi satu file JavaScript?

Saya benar-benar tidak melihat masalah dengan memberikan alat kepada masyarakat. Dan saya yakin 100% akan ada devs yang akan menyalahgunakannya. Tetapi juga pengembang yang tahu persis cara menggunakannya. Tetapi bukankah kita memiliki situasi yang sama dengan konstruksi bahasa apa pun?

+1 untuk tujuan pembuatan kode. Dan saya setuju dengan @rpokrovskij , mengapa kami memilih TypeScript, saya juga dapat menggunakan JavsScript secara langsung, Hanya karena sepertinya C#, dan memiliki dukungan ide.

@greendimka Saya tidak tahu bagaimana ini bisa bekerja tanpa menyimpang dari dan menambah kompleksitas substansial pada Modul ES.

@xiexin36 TypeScript sepertinya lebih mirip JavaScript daripada C# bagi saya.
Ada kesamaan antara JavaScript dan C#, tetapi gagasan mereka tentang class sangat berbeda.

@xiexin36 untuk pembuatan kode Anda masih dapat menggunakan augmentasi modul (seperti yang saya sebutkan sebelumnya di utas ini ). Secara sintaksis itu tidak "semudah" seperti kelas parsial, tetapi Anda dapat menyelesaikan tugas yang sama.

@aluanhaddad Yah, ini bekerja sangat sederhana: kelas parsial tidak mengubah struktur kode dengan cara apa pun. Mereka hanya mengizinkan kita untuk menulis definisi kelas yang sama di beberapa file (yang dikompilasi menjadi JS tunggal).

@aluanhaddad Sebenarnya: javascript tidak memiliki konsep kelas (kelas ES6 hanya menyediakan gula sintaksis). Jadi, jika kita mencoba mengikuti konsep memiliki TypeScript selemah JavaScript - tidakkah kita harus membuang kelas dari TypeScript? Bukankah seharusnya kita kembali ke JavaScript?

Kelas @greendimka ES6 dan kelas TypeScript adalah satu dan sama.
TypeScript tidak bertujuan untuk menambahkan konstruksi tambahan ke runtime JavaScript.

Kelas ES6 _sangat_ tidak bersemangat. Itu tidak berarti bahwa JavaScript bukan bahasa yang kuat (itu). TypeScript menyediakan pengetikan statis untuk menangkap kesalahan pada waktu desain, menyediakan perkakas berkualitas tinggi, memungkinkan spesifikasi antarmuka komponen yang sangat presisi dan ketat, dan secara umum meningkatkan produktivitas.

Kelas ES6 _sangat_ loyo tetapi untuk TypeScript untuk memperkenalkan gagasannya sendiri tentang kelas akan melanggar langsung tujuan desainnya.

Cukup hindari kelas dan masalah Anda akan terpecahkan.

Yah, ini bekerja dengan sangat sederhana: kelas parsial tidak mengubah struktur kode dengan cara apa pun. Mereka hanya mengizinkan kita untuk menulis definisi kelas yang sama di beberapa file (yang dikompilasi menjadi JS tunggal).

Dan menghancurkan hampir semua alat yang dikenal manusia? Tidak terima kasih.

@david-driscoll Terima kasih, saya akan mencobanya, tetapi saya juga menggunakan Angular 2.0, saya ingin tahu apakah saya membuat kode dengan
@Input atau @Output , itu akan berhasil, bagaimanapun saya akan mencobanya.

@aluanhaddad sungguh menyakitkan melihat bagaimana Anda terus mengulang "kelas? javascript tidak memiliki kelas". Hapus kelas dari kepala Anda, tinggalkan hanya JavaScript, dan sekarang dengarkan: pengembang yang menggunakan pembuatan kode ingin memiliki satu unit kompilasi di beberapa file. Tidak ada kelas dalam bahasa ini, hanya fungsi? OK, kami ingin fungsi parsial. Dan JavaScript hampir siap untuk ini: fungsi di sana dapat digunakan sebelum deklarasi. Di sana kita dapat menemukan masalah lain tentu saja (misalnya untuk memastikan bahwa semua bagian/file dimuat ke lingkungan eksekusi), tetapi mereka dapat dipecahkan, dan sebenarnya kita ingin memiliki unit kompilasi parsial di TypeScript, bukan di JavaScrpipt. TypeScript siap untuk ini 100%.

Dan omong-omong, tim TypeScript, beri kami fungsi parsial juga! Dan tolong beri tahu hal yang sama kepada tim C#, karena kami memiliki "fungsi dalam fungsi" untuk saat ini. :)

Hanya untuk memastikan, Anda menyadari bahwa fungsi parsial memiliki arti yang sangat spesifik dan apa yang Anda gambarkan bukan fungsi parsial dengan imajinasi apa pun?
Pembuatan kode berguna, saya juga menggunakannya.

@aluanhaddad . Apakah Anda memahami istilah "satu unit kompilasi dalam beberapa file"? Javascript tentu saja bukan bahasa kompilasi tetapi a) fungsi harus diurai sepenuhnya sebelum dieksekusi dan kita dapat menamai ini "kompilasi" b) Typescript adalah bahasa kompilasi.

Untuk membantu imajinasi Anda:

function partial func(arguments) {
  return function() {
    return codegenerated(arguments);
  };
}

function partial func(arguments) {
   function codegenerated(arguments){
      // ...
   }
}

Saya juga tidak sering menggunakan kelas parsial: untuk menggunakannya secara efektif kita perlu menyimpan parameter pembuatan kode di bagian "manual" dan untuk membaca konfigurasi ini kita harus memiliki parser bahasa yang baik (bukan refleksi). Tapi begitulah adanya: kelas parsial hanya satu instrumen dari banyak untuk membuat pembuatan kode nyaman.

@rpokrovskij
Saya minta maaf jika saya datang sebagai antagonis. Saya tidak bermaksud menyinggung atau tidak hormat.

Contoh Anda memiliki aspek-aspek yang memerlukan deskripsi yang cukup formal. Proposal ini awalnya bukan tentang mengaktifkan skenario pembuatan kode secara langsung.

@aluanhaddad....
"Cukup hindari kelas dan masalah Anda akan terpecahkan" - serius, itu adalah solusi untuk masalah?! Mungkin jika saya menghindari penggunaan JavaScript - saya dapat menyelesaikan masalah dari seluruh diskusi ini. Juga solusi, bukan? Sayangnya kita memiliki bahasa menyebalkan ini di alam semesta kita karena cukup beruntung untuk masuk ke web bertahun-tahun yang lalu. Bagaimanapun, ini adalah offtopic.

"hancurkan hampir semua alat yang dikenal manusia" - bagaimana mungkin??? Bagaimana?!?! Saya mencoba membayangkan memecahkan sesuatu dengan menggunakan kelas parsial di TypeScript, tetapi saya tidak bisa. Saya tidak bisa. Tolong, bantu saya di sini dengan beberapa contoh kehidupan nyata.

Sekarang bayangkan Anda telah membuat mobil untuk mengangkut kotak. Ia bekerja tanpa masalah. Anda menyewa seorang pekerja, yang memuat mobil. Pekerja itu mengambil dua kotak sekaligus dan memasukkannya ke dalam mobil. Masih semuanya bekerja dengan baik.
Suatu hari pekerja pergi ke perusahaan lain dan Anda menyewa yang baru. Yang baru mengambil satu kotak, memuatnya, mengambil satu kotak lagi dan memuatnya juga. Logikanya: semuanya baik-baik saja. Tapi Anda berlarian dan berteriak: berhenti, berhenti, kami mengalami kegagalan sistem! :)

"Cukup hindari kelas dan masalah Anda akan terpecahkan" - serius, itu adalah solusi untuk masalah?! Mungkin jika saya menghindari penggunaan JavaScript - saya dapat menyelesaikan masalah dari seluruh diskusi ini. Juga solusi, bukan? Sayangnya kita memiliki bahasa menyebalkan ini di alam semesta kita karena cukup beruntung untuk masuk ke web bertahun-tahun yang lalu. Bagaimanapun, ini adalah offtopic.

ES2015 pasti memiliki banyak hal yang salah. ES5.1 pasti memiliki banyak kesalahan. Menurut pendapat saya, kurangnya kelas bukanlah salah satunya. Maksud saya adalah bahwa dengan menggunakan teknik seperti pola modul pengungkap, Anda meniadakan kebutuhan akan kelas parsial. TypeScript menyediakan gula untuk membuka pola modul, ruang nama.

"hancurkan hampir semua alat yang dikenal manusia" - bagaimana mungkin??? Bagaimana?!?! Saya mencoba membayangkan memecahkan sesuatu dengan menggunakan kelas parsial di TypeScript, tetapi saya tidak bisa. Saya tidak bisa. Tolong, bantu saya di sini dengan beberapa contoh kehidupan nyata.

Jika Anda menggunakan Modul ES, ini bermasalah. Alat apa pun yang bergantung pada artefak fisik kompiler yang memiliki korespondensi dengan rekan-rekan mereka yang tidak dikompilasi akan tunduk pada ini. Yang mengatakan, TypeScript dapat menyesuaikan ini dalam memancarkan, perubahan besar, tetapi kemudian akan memancarkan JavaScript yang tidak cocok dengan TypeScript yang Anda tulis.

Jadi, pada dasarnya, evolusi bahasa ditahan oleh alat, yang tidak akan pernah berkembang tanpa evolusi bahasa.
Maaf, tapi saya melihat di sini hanya mencari alasan untuk tidak berevolusi.

Apa manfaat yang diberikan kelas parsial, yang belum bisa Anda lakukan dengan bahasa dengan cara yang berbeda? Ini gula sintaksis yang bagus, tentu saja, tapi apa keuntungan sebenarnya? Apakah ada contoh konkret selain membuatnya lebih seperti C#?


Selain: Sebagai catatan saya mulai sebagai Pengembang C#, pindah ke JavaScript / C# dari sana. Setelah TypeScript 0.8 diumumkan, saya dijual, bukan karena C# untuk JavaScript, tetapi karena menggunakan JavaScript yang ketat dan membuatnya lebih baik untuk pengembang yang menyukai jenis C# yang kuat.

TypeScript bukan C#, dan tidak boleh secara ketat mewarisi fitur dari C# hanya karena C# memilikinya. Sama seperti C# seharusnya tidak mewarisi fitur dari TypeScript. Saya tidak dapat menghitung berapa kali saya menginginkan fitur seperti tipe serikat pekerja di C # karena mereka sangat mengagumkan untuk TypeScript, tetapi mereka belum tepat untuk bahasanya.


Sejauh ini saya sudah membaca Pembuatan Kode dan Organisasi Kode.

Pembuatan Kode, lihat Modul Augmentasi ada beberapa kekurangan yang saya sebutkan di sini tapi saya yakin itu bisa diperbaiki.

Organisasi Kode, saya kira menggunakan wilayah (lol)? Ada banyak cara lain untuk mengatur kode Anda, jika Anda memiliki satu kelas Tuhan (untuk alasan apa pun), Anda selalu dapat membaginya menjadi banyak kelas Tuhan. Di permukaan kelas dewa adalah impor semua orang melihat dan menggunakan, di bawah selimut namun terbuat dari banyak kelas mungkin sebagai properti dari kelas dewa. Jika Anda menggunakan kelas parsial untuk organisasi, saya berpendapat Anda perlu sedikit memperbaiki kode Anda untuk mencoba dan SOLID ify kode Anda.

Saya telah dapat memasukkan augmentasi ke dalam sebagian besar skenario pembuatan kode yang saya temui hingga saat ini.

Untuk Omnisharp-Client saya menggunakan ekstensi antarmuka di sini di mana OmniSharp.Api.V2 dihasilkan melalui refleksi di C#. Di bagian bawah file saya memiliki alat yang mematikan semua metode untuk antarmuka itu.

Untuk RxJS kami gunakan to untuk memetakan semua metode kami yang ada di Observable .

Saya tidak bisa memikirkan beberapa masalah dengan kelas parsial. Misalnya jika kita diberikan 3 kelas parsial.

  • MyAwesomeClass1.ts
  • MyAwesomeClass2.ts
  • MyAwesomeClass3.ts

Cakupan: Modul Global (menggunakan namespace / module )

Kompilasi global adalah tempat yang tampaknya paling mudah. Karena TypeScript sudah menggabungkan ruang nama bersama.

Jika tsconfig.json hanya berisi jalur file untuk Kelas1 dan Kelas2 maka apa pun yang ada di Kelas3 tidak secara otomatis digabungkan.

  • Pada awalnya ini tampak seperti kesalahan pengguna, tetapi tidak akan segera terlihat mengapa metode dari Class3 tidak disertakan. Ini adalah masalah kegunaan besar yang akan menyebabkan kebingungan.

Cakupan: Modul Eksternal (impor / ekspor)

Dengan kompilasi eksternal, setiap file benar-benar dianggap modul (atau Majelis neraka di dunia .NET) karena setiap modul memiliki daftar eksplisit semua dependensinya (impor) dan semua api publiknya (ekspor).

Bagaimana Anda bernalar tentang skenario-skenario ini?

Diberikan hanya satu referensi file, apa perilaku kelas?
Apakah secara otomatis menggabungkan Class2 dan Class3?

  • Apakah definisi default Class1, Class2 dan Class3 semuanya mengekspor nilai yang sama persis?
  • File apa yang dipancarkan ke disk?
  • Seperti apa tampilan JavaScript yang mendasari untuk semua format yang didukung (amd, umd, commonjs, dll)
// somefile.ts
import { MyAwesomeClass } from 'MyAwesomeClass1';

new mac = new MyAwesomeClass();
mac. // What methods are available here?

Apakah kita harus mengimpor semua instance kelas secara eksplisit? (Jika kita melakukan itu mengalahkan tujuan imo).
Apa yang terjadi ketika Anda mengimpor semuanya dalam satu file, tetapi tidak yang lain, ke metode yang dibawa?
Ini dapat menyebabkan kesalahan yang sangat aneh mengingat grafik ketergantungan yang kompleks di mana kelas digunakan sekali, tanpa parsial tambahan. Apakah nilainya akan ditambah? atau akankah metode tersebut secara ajaib tidak berfungsi sampai file lain dimuat yang membawa mereka masuk?

// somefile.ts
import { MyAwesomeClass } from 'MyAwesomeClass1';
import { MyAwesomeClass } from 'MyAwesomeClass2'; // or maybe import 'MyAwesomeClass2';
import { MyAwesomeClass } from 'MyAwesomeClass3'; // or maybe import 'MyAwesomeClass3';

new mac = new MyAwesomeClass();
mac. // What methods are available here?

@david-driscoll Hanya dua sen saya di sini:

Ini gula sintaksis yang bagus, tentu saja, tapi apa keuntungan sebenarnya?

Bukankah gula sintaksis yang bagus adalah inti dari bahasa apa pun? Dari sudut pandang operatif, yang kita butuhkan hanyalah loop, if-clauses dan iterasi untuk melakukan semuanya. Sisanya hanyalah _gula sintaksis yang bagus_ agar lebih produktif dan memberikan kualitas non-fungsional serupa lainnya.

Dan sementara bahasa umumnya bagus dalam bagian operasional dari instruksi komputer, mereka umumnya payah dalam bagian organisasi penulisan kode. Kami memiliki artefak ad-hoc budaya ini seperti objek, kelas, warisan dan semacamnya, tetapi tidak ada landasan teoretis yang kuat, afaik, yang benar-benar menjelaskan domain operasi pengorganisasian dan semua abstraksi yang kami coba bangun dan wakili dalam kode sumber kami secara berurutan. untuk dapat bekerja dengannya dengan cara yang baik.

Ada dua hal yang saya sukai dari TypeScript: 1. Ini memungkinkan kita menggunakan javascript yang diketik sehingga tiba-tiba dapat dikelola untuk membangun sistem yang kompleks di klien. 2. Sistem tipe sangat ekspresif (karena dipaksa untuk dapat mengekspresikan semua jenis pola dalam javascript yang dapat ditulis orang tanpa batasan sistem tipe).

Tetapi dalam hal penataan kode, saya pikir itu tidak terlalu menyebalkan daripada bahasa lain. Dan saya berharap kita bisa lebih inovatif di sini. Beri pengguna lebih banyak kebebasan untuk bereksperimen dengan bagian organisasi bahasa. Membuka diri dan berjuang untuk ekspresi struktural baru alih-alih membatasi dan curiga.

Kelas parsial tidak hanya sangat nyaman untuk pembuatan kode secara khusus, tetapi juga meningkatkan kebebasan dalam organisasi secara umum. Kebebasan yang kita butuhkan untuk keluar dari tar-pit organisasi kode ini.

@david-driscoll apa gunanya memiliki sebagian? Nah, sekali lagi: pembuatan kode.
Apa yang salah dengan solusi yang Anda usulkan? Ini adalah solusi. Namun solusi lain (dan solusi yang cukup kotor). Kami sudah memiliki bahasa yang menyebalkan (javascript), yang diisi dengan solusi. Alih-alih memikirkan tugas utama mereka, pengembang javascript menghabiskan banyak waktu untuk memikirkan solusinya. Dengan filosofi yang Anda usulkan, kami dapat membuang seluruh bahasa TypeScript. Karena (kejutan, kejutan) seluruh jenis sistem dapat disimulasikan dalam javascript murni - dengan menggunakan solusi. Mengapa peduli dengan bahasa yang lebih ekspresif (seperti TypeScript) jika Anda dapat mensimulasikan apa pun dengan solusi? Mengapa menulis satu baris kode ketika hal yang sama dapat ditulis dalam dua puluh baris? Kembalikan gaji berdasarkan sejumlah baris kode yang ditulis! Kode pendek dan ekspresif untuk pussies, bukan?

Dan tidak: permintaan untuk memiliki sebagian dalam TypeScript tidak didasarkan pada gagasan bahwa C# memilikinya. Saya tidak percaya TypeScript harus memiliki sesuatu hanya demi memilikinya karena bahasa lain memilikinya.

Dan akhirnya: mengapa Anda berpikir bahwa jika Anda tidak menggunakan sesuatu - tidak ada yang membutuhkannya?

@greendimka Saya tidak mencoba memicu permusuhan : shield:. Saya hanya mencoba memahami skenario atau jika ada skenario yang tidak saya sadari yang sejujurnya sangat mungkin!

Sekarang perlu diingat, saya tidak berada di Tim TypeScript, saya hanya seorang advokat, tetapi tim ini cukup diam di sini. Tim mungkin akan sangat cocok ketika mereka memiliki sesuatu yang spesifik untuk dikatakan, dan saya akan tunduk kepada mereka jika mereka memilih untuk melakukannya.

Salah satu penyewa utama yang dipegang oleh tim TypeScript adalah mencoba dan menjaga agar TypeScript tetap sinkron dengan arah ECMAScript, dan untuk menghindari membuat fitur spesifik apa pun yang dapat menyebabkannya menyimpang dari keseluruhan arah pengembangan JavaScript.

Bukannya saya tidak akan menggunakannya (mungkin saya akan menggunakannya jika ada). Masalahnya adalah seperti yang ada dalam masalah ini, sebagian kelas mungkin memiliki peringatan sehingga tampaknya diragukan itu akan diimplementasikan dalam waktu dekat. Mungkin akan tetap seperti ini untuk sementara waktu sampai a) menjadi fitur yang harus dimiliki oleh pemangku kepentingan bernilai tinggi atau b) proposal masuk ke tahap selanjutnya dari TC39.

Saya tidak melihat Modul Augmentasi sebagai solusi. Ini memungkinkan Anda untuk menambah sistem tipe, dan memungkinkan banyak skenario Pembuatan Kode yang telah dirinci di utas ini. Ini adalah langkah menuju fitur bahasa lainnya.

  • Apakah itu jelek? Benar-benar, jelek sekali. Yang mengatakan jika Anda membuat kode, apa bedanya? Hanya alat generasi Anda yang perlu khawatir tentang cara menambah kelas. Setelah Anda menjalankan alat pembuat kode Anda, dan memasukkan modul Anda, Anda mendapatkan kesalahan intellisense dan kompilasi penuh, dll.

  • Apakah itu sempurna? Jauh dari itu! Saya melihat skenario yang jauh lebih umum dengan mixin yang perlu didukung di tingkat bahasa. Dan saya pikir sesuatu yang sejalan dengan dekorator seperti yang diusulkan di sini masuk akal, meskipun sekali lagi tidak ada proposal khusus.

@david-driscoll, maaf karena sangat kasar. Saya benar-benar cenderung berdiri di sisi kemajuan positif.

Saya ingin ini sehingga saya bisa meletakkan implementasi statis di kelas parsial.

Karena sepertinya ini tidak akan segera membuahkan hasil, saya ingin mengusulkan solusi yang kami temukan. Ada beberapa komentar seperti ini, tetapi saya tidak melihatnya dengan bacaan spesifik ini.

Kami ingin Partials untuk digunakan dalam skenario pembuatan kode di mana kami ingin dapat memperluas kode TypeScript yang kami buat. Namun, kami menghasilkan model yang memiliki saling ketergantungan sehingga mewarisi dari kelas kami tidak berfungsi dengan baik dalam pengertian tradisional. Kelas yang dihasilkan yang mereferensikan kelas lain tidak berakhir dengan tipe objek yang tepat yang direferensikan dan kita akan berakhir dengan pola pabrik yang kompleks untuk membuat tipe instans yang benar dibuat.

Kami akhirnya mengubah kelas yang kami hasilkan menjadi kelas dasar, tetapi hanya dalam deklarasi kelas. Kami kemudian membuat kelas rintisan yang diwarisi dari kelas dasar baru kami. Kami kemudian dapat memperluas kelas baru ini dan mereka akan mewarisi semua konten mereka dari kelas dasar.

Sebagai contoh:
Jika kita membuat Person kelas, sekarang kita akan menghasilkan PersonBase. Semua kode yang dihasilkan masuk ke kelas ini. Kami juga akan menghasilkan Person kelas kosong yang memperluas PersonBase. Kelas ini hanya akan dihasilkan sekali. Kami kemudian meletakkan semua kode yang kami buat di PersonBase, dan semua kode kustom secara manual masuk ke Person. Semua referensi yang dihasilkan ke Person tetap sebagai Person dan bukan PersonBase. Dengan cara ini semua IntelliSense terus bekerja.

File 1: Kelas Dasar

module ViewModels {
    export class PersonBase {
        // Generated members
        public anotherPerson: Person;
        constructor(){
            // Generated constructor code
        }
    }
}

File 2: Kelas Sebenarnya

module ViewModels {
    export class Person extends PersonBase {
        // Custom methods
        public NewVariable: string = "NewVar";
        constructor() {
            super();
            // Custom constructor code
        }
    }
}

Ini telah memecahkan masalah kelas parsial kami dengan kode yang dihasilkan. Kudos to Andrew Scott untuk datang dengan ide.

Saya juga sangat menyukai ini, karena saya membuat beberapa kode dengan pembuat kode, dan saya perlu menambahkan beberapa perubahan padanya. Kelas parsial akan memungkinkan pembuatan ulang kode tanpa harus menambahkan perubahan lagi nanti (yang mungkin besar atau rumit)

Ada alasan penting untuk memiliki sebagian kelas yang menurut saya belum disebutkan: secara bertahap memigrasikan JS ke TS. Dalam Javascript, khususnya pra-ES6, kelas dapat terlihat seperti sekumpulan:

Foo.prototype.someFunction = function() {/*....*/}

Dan ini dapat tersebar di beberapa file tanpa penanganan khusus. Mengubah basis kode seperti itu menjadi TypeScript modern saat ini membutuhkan fungsi yang bergerak sehingga semua anggota kelas berada dalam file yang sama, yang bisa menjadi perubahan yang cukup invasif. Dengan kelas parsial, migrasi dapat dilakukan hanya dengan menggunakan suntingan lokal.

@RyanCavanaugh Anda menyebutkan bahwa semua yang diminta di sini dapat ditangani secara sintaksis dengan sintaks TypeScript lainnya:

Saya pikir proposal mixin memiliki lebih banyak pertanyaan terbuka. Proposal kelas parsial di sini hanyalah kodifikasi dari hal-hal yang sudah diizinkan di TypeScript, hanya dengan beberapa gula sintaksis (fitur ini benar-benar dapat dilakukan sebagai pemetaan ulang sintaksis untuk hal-hal yang sudah kita miliki).

Jadi bagaimana cara melakukan ini di TypeScript?:
File1.ts:

// Imagine this file is code generated and could be regenerated during development
export partial class Contact
{
    firstName: string;
    lastName: string;
    partial OnInit( args: any ) : void;
    constuctor( args: any )
    {
        this.OnInit( args );
    }
}
export class Address
{
    addr: string;
    city: string;
    state: string;
    zip: string;
}

File2.ts

// See where I'm going with this? This file would be hand edited and allows me to specify associations and children.
partial class Contact
{
    Addresses: string[] = [];
    partial OnInit( args: any ) void
    {
        this.firstName = args.firstName;
        this.lastName = args.lastName;
        this.Addresses.push( new Address() );
    }
}

Transpiling di atas akan memancarkan satu kelas JS untuk Kontak, sesuatu seperti ini:

var Contact = (function () {
    function Contact() {
         this.Addresses = [];
   }
   Contact.prototype.constuctor = function (args) {
       this.OnInit( args );
   };
   Contact.prototype.OnInit = function (args) {
       this.firstName = args.firstName;
       this.lastName = args.lastName;
       this.Addresses.push(new Address());
   };
   return Contact;
})();

var Address = (function () {
    function Address() {
    }
    return Address;
})();

Perhatikan bahwa pada akhirnya saya ingin satu kelas bernama Kontak dan saya tidak ingin harus mensubklasifikasikan dua kelas terpisah menjadi yang ketiga.

@cosmoKenney

Berikut ini contoh sesuatu yang akan berhasil. Ini tidak secara sintaksis surgared seperti partial namun bekerja dan merupakan solusi yang sangat fungsional.

// address.ts
export class Address
{
    addr: string;
    city: string;
    state: string;
    zip: string;
}
// contact.impl.ts
import { Address } from './address';

// Class implementation, do the things here that are not code generated
export class Contact {
    firstName: string;
    lastName: string;
    addresses: Address[];
    constructor(args: any) {
        this.onInit(args);
    }
}
// extending the interface here
// define methods you know will need in the constructor only
// This only applies to the constructor however
export interface Contact {
    onInit(args: any): void;
}
// contact.partial.ts
import { Contact } from './contact.impl';

// Implement the extended contract here
Contact.prototype.onInit = function(this: Contact, args: any) {
    this.addresses = args.addresses.concat();
    // do stuff;
};

// Adding another method (not part of the extended interface)
Contact.prototype.somethingAwesome = function(this: Contact) {
    // do awesome stuff here
};

// Tell TypeScript "I added this here!!!!"
declare module './contact.impl' {
    interface Contact {
        somethingAwesome();
    }
}
// contact.ts
import { Contact } from './contact.impl';
import './contact.partial';

// Bring it all together (perhaps there are more than one partial class?)
export { Contact };
// main.ts
import { Contact } from './contact';

// use the contact!
const contact = new Contact(['my', 'args']);
const {firstName, lastName} = contact;
contact.somethingAwesome();

Atau Anda juga dapat membuat kode antarmuka dan menggunakan ekstensi antarmuka yang mengimplementasikannya.

Mungkin juga ada cara untuk menggunakan fungsi Mixin yang baru, namun saya sendiri belum cukup mendalaminya untuk memberikan jawaban yang memenuhi syarat.

@david-driscoll Wow. Kepalaku meledak begitu saja.

Saya ingin tahu apakah komunitas akan berakhir dengan garpu, yang hanya mendukung sebagian kelas tanpa menimbulkan masalah.
Sejauh ini belum mendengar argumen nyata terhadap kelas parsial. Hanya beberapa alasan untuk membenarkan kemalasan.

@greendimka

Saya ingin tahu apakah komunitas akan berakhir dengan garpu, yang hanya mendukung sebagian kelas tanpa menimbulkan masalah.
Sejauh ini belum mendengar argumen nyata terhadap kelas parsial. Hanya beberapa alasan untuk membenarkan kemalasan.

Tidak yakin apa yang Anda coba katakan di sini. Tetapi jika perasaan keseluruhan dalam komunitas adalah bahwa kita dapat mencapai hasil yang sama dengan menggunakan fitur bahasa yang ada, maka saya hanya perlu beberapa contoh bagaimana melakukannya. Apa yang diposting @david-driscoll di atas jauh di luar pemahaman saya. Dan tampaknya tidak sepenuhnya menyelesaikan masalah. Bahkan, dari apa yang saya tahu, dia salah mengartikan niat saya.
Perhatian utama saya adalah membuat kode untuk menghasilkan properti skalar kelas, seperti kelas pojo atau model. Tetapi saya harus dapat, dalam file terpisah, atau bahkan dalam file yang sama, tetapi tidak dalam definisi kelas utama menambahkan properti asosiasi (sehingga saya dapat menempelkan definisi utama yang baru dibuat dengan kode di atas yang asli).
Misalnya kelas Kontak saya dari atas akan mendapatkan kode yang dihasilkan dengan firstName dan lastName. Tapi, dalam definisi terpisah saya adalah di mana saya akan menambahkan definisi dan inisialisasi kumpulan objek Alamat.
Pembuat kode saya hanya mengetahui atribut kelas, bukan asosiasi, sehingga tidak dapat mengkodekan kumpulan alamat -- seperti yang dilakukan pada contoh david.

@cosmoKenney tidak sepenuhnya jelas di mana alamatnya seharusnya ada. Maafkan saya untuk mendapatkan konteks yang salah. Saya hanya mencoba membantu memberikan alternatif. Ada banyak fungsi yang memungkinkan perilaku serupa tanpa memasukkan sesuatu ke dalam kompiler seperti kelas parsial, yang memiliki banyak pertimbangan tambahan dan masalah potensial untuk mengimplementasikan kedua sistem modul (internal/eksternal).

Dalam kasus Anda menghasilkan kelas dasar abstrak, atau generasi antarmuka akan berfungsi, maka kelas Anda yang lain mewarisi dari itu. Maka fakta bahwa kelas Anda dibuat masih tersembunyi.

yaitu:

// address.partial.ts
export interface IAddress
{
    addr: string;
    city: string;
    state: string;
    zip: string;
}

// address.ts
import { IAddress } from './address.partial';

export class Address
{
    constructor(args: any) {

    }
}
export interface Address extends IAddress{}

// contact.partial.ts
import { IAddress } from './address.partial';

export interface IContact {
    firstName: string;
    lastName: string;
    addresses: IAddress[];
}

// contact.ts
import { Address } from './address';
import { IContact } from './contact.partial';

// Class implementation, do the things here that are not code generated
export class Contact {
    addresses: Address[] = [];

    constructor(args: any) {
        this.firstName = args.firstName;
        this.lastName = args.lastName;
        this.addresses.push( new Address("address?") );
    }

    public somethingAwesome() {
        //
    }
}
export interface Contact extends IContact {}

// main.ts
import { Contact } from './contact';

const contact = new Contact(['my', 'args']);
const {firstName, lastName} = contact;
contact.somethingAwesome();

@cosmoKenney : @david-driscoll menawarkan solusi yang menarik, tetapi masih tidak memiliki kemudahan kelas parsial nyata. Seperti yang ditunjukkan oleh eksperimen pribadi saya - pengembang tidak menggunakan "sebagian" yang dibuat dengan cara ini. Meskipun ini adalah solusi solusi yang baik, kemudahan dan kenyamanan parsial tidak ada.

Saat ini saya tidak tahu bagaimana kompiler TypeScript bekerja secara internal. Saya hanya bisa berasumsi bahwa itu membaca semua file sumber, memprosesnya, dan mengeluarkan file JS. Jika demikian - saya tidak melihat masalah dalam membaca satu kelas dari beberapa file sumber. Jika dua atau lebih file sumber dari satu kelas menyediakan kode yang saling bertentangan (properti yang sama didefinisikan dua kali), kompiler hanya melempar pengecualian. Sama seperti jika Anda menulis kode yang tidak valid secara sintaksis.

@greendimka , @david-driscoll
Saya mencoba mengkompilasi contoh David dari atas, dan ts tidak menyukainya:

C:\TestProjects\TypeScriptFakePartialClassTest>tsc -m amd address.partial.ts address.ts contact.partial.ts contact.ts main.ts
address.ts(4,14): error TS2300: Duplicate identifier 'Address'.
address.ts(10,18): error TS2300: Duplicate identifier 'Address'.
contact.ts(7,14): error TS2300: Duplicate identifier 'Contact'.
contact.ts(11,14): error TS2339: Property 'firstName' does not exist on type 'Contact'.
contact.ts(12,14): error TS2339: Property 'lastName' does not exist on type 'Contact'.
contact.ts(20,18): error TS2300: Duplicate identifier 'Contact'.
main.ts(5,8): error TS2459: Type 'Contact' has no property 'firstName' and no string index signature.
main.ts(5,19): error TS2459: Type 'Contact' has no property 'lastName' and no string index signature.

Selain itu saya setuju dengan @greendimka bahwa ini terlalu rumit untuk digunakan ratusan kali dalam aplikasi besar.

@greendimka Saya juga tidak tahu cara kerja kompiler, tetapi jangan meremehkan tugasnya. JavaScript bukan .NET dan modul tidak tersedia secara global (Anda harus benar-benar mengimpornya)

Saya ingin melihat ini diterapkan, tetapi tugas ini memunculkan beberapa hal yang perlu dipikirkan dengan cermat, seperti:

  • Jika Anda mendefinisikan bagian dari kelas pada file A, bagian pada file B, yang mana yang harus berisi kelas penuh setelah transpiling? Yang baru harus dibuat?
  • Haruskah semua file yang berisi sebagian barang mengekspor kelas yang sama?
  • Bagaimana cara menghindari ketergantungan siklik jika saya memerlukan file utama pada file tambahan itu?
  • Bagaimana jika saya mengekspor lebih banyak hal pada modul daripada hanya kelas itu sendiri?
  • Pemeriksaan konflik nama?

dan seterusnya...

@greendimka Lihat tanggapan saya di bawah ini: (EDIT: ini ditargetkan pada @WoLfulus , maaf @greendimka):

Jika Anda mendefinisikan bagian dari kelas pada file A, bagian pada file B, yang mana yang harus berisi kelas penuh setelah transpiling? Yang baru harus dibuat?

Saya akan sangat senang jika file A.js memiliki definisi lengkap, dan file B dimatikan. Mungkin dengan komentar kalengan. Sebagian besar dari kita tetap melakukan bundling sehingga banyak sekali file .js yang dibundel pada dasarnya menjadi sebuah pemikiran pada akhirnya.

Haruskah semua file yang berisi sebagian barang mengekspor kelas yang sama?

Ini cukup banyak dijawab oleh tanggapan saya untuk pertanyaan pertama.

Bagaimana cara menghindari ketergantungan siklik jika saya memerlukan file utama pada file tambahan itu?

Saya tidak tahu. Bukankah tugas pemuat modul untuk mengenali skenario ini?

Bagaimana jika saya mengekspor lebih banyak hal pada modul daripada hanya kelas itu sendiri?

Saya tidak melihat masalah dengan ini. Dengan kata lain jika B.ts memiliki definisi parsial dan beberapa kelas non-parsial lainnya, maka B.js harus berisi komentar kalengan seperti yang disebutkan di atas, DAN definisi kelas non-parsial. Sederhana, saya pikir.

Pemeriksaan konflik nama?

Bagaimana Anda akan berakhir dengan konflik nama? Jika maksud Anda di kelas, maka kata kunci "sebagian" akan menyelesaikannya. Tetapi kemudian jika dua file lain sama-sama mendefinisikan kelas dengan nama yang sama, tetapi tanpa kata kunci "parsial", kompilator akan mengeluarkan kesalahan tentang tipe duplikat -- seperti yang terjadi sekarang. Tetapi jika Anda berbicara tentang dua definisi parsial dari kelas yang sama yang mendefinisikan properti atau metode dengan nama yang sama, kompiler akan mengeluarkan kesalahan tentang anggota duplikat -- seperti yang terjadi sekarang.

@WoLfulus , @cosmoKenney telah menjawab dengan baik. Hanya untuk membuatnya lebih baik dengan pertanyaan pertama Anda (tentang file A dan B): sebagai perancang bahasa, seseorang memiliki hak istimewa untuk mendefinisikan aturan. Maksud saya file A mungkin memiliki kode seperti "partial class X" dan file B mungkin memiliki kode seperti itu "partial(fileX) class X", yang akan menghasilkan fileX.js.

@cosmoKenney

Bagaimana cara menghindari ketergantungan siklik jika saya memerlukan file utama pada file tambahan itu?
Saya tidak tahu. Bukankah tugas pemuat modul untuk mengenali skenario ini?

TypeScript tidak memiliki pemuat modul.

@greendimka

Saya ingin tahu apakah komunitas akan berakhir dengan garpu, yang hanya mendukung sebagian kelas tanpa menimbulkan masalah.
Sejauh ini belum mendengar argumen nyata terhadap kelas parsial. Hanya beberapa alasan untuk membenarkan kemalasan.

Itu bukan ide yang bagus. Misalnya, sudahkah Anda mempertimbangkan bagaimana Anda akan mempertahankan fork Anda saat impor dinamis ditambahkan?
Juga, banyak argumen telah dibuat terhadap kelas parsial. Memecah korespondensi sumber ke sumber antara file TypeScript dan JavaScript bertentangan dengan prinsip utama bahasa tersebut. Saya membayangkan bahwa suatu fitur perlu mengaktifkan skenario yang jauh lebih berharga daripada kelas parsial agar dapat dipertimbangkan. Kemungkinan besar masih akan ditolak.

@WoLfulus , @cosmoKenney telah menjawab dengan baik. Hanya untuk membuatnya lebih baik dengan pertanyaan pertama Anda (tentang file A dan B): sebagai perancang bahasa, seseorang memiliki hak istimewa untuk mendefinisikan aturan. Maksud saya file A mungkin memiliki kode seperti "partial class X" dan file B mungkin memiliki kode seperti itu "partial(fileX) class X", yang akan menghasilkan fileX.js.

Saya tidak berpikir Anda mendapatkan pesan Anda. Itu membuatnya terdengar seolah-olah Anda merasa bahwa batasan apa pun yang pernah Anda temui untuk mengekspresikan diri Anda dalam bahasa apa pun ada karena alasan yang sepenuhnya sewenang-wenang.
Juga pertanyaan @WoLfulus ' tidak dijawab, setidaknya tidak memuaskan saya.

pakaian api don

TL;DR: Ini tidak terjadi. Jika Anda di sini di komentar nomor 189 dan ingin menyatakan ketidaksetujuan Anda dengan itu, harap baca seluruh utas terlebih dahulu, karena alasan yang sangat bagus untuk tidak menambahkan ini telah dibahas secara luas di atas.

Interpretasi kami tentang situasi ini adalah sebagai berikut:

  • TypeScript sudah memiliki terlalu banyak fitur kelas khusus TS (deklarasi properti konstruktor, inisialisasi anggota, dekorator yang belum selesai, pengubah akses, implements , dll.) untuk sesuatu yang benar-benar dimaksudkan untuk menjadi "ES6 + Jenis" . Bagian dari itu adalah kesalahan kita (arah desain asli kami adalah umumnya terlalu OOP) dan bagian dari itu adalah kesalahan ES6 ini (usulan kelas berpindah-pindah lima tahun yang lalu dan kami akhirnya memiliki fitur yang tidak berhasil). Menambahkan fitur kelas khusus TS lainnya adalah hal lain di punggung unta yang harus kita hindari jika kita bisa.
  • Jelas, masa depan JavaScript adalah modul. Kelas parsial hanya masuk akal dan beroperasi dengan baik dalam model "sup global". Mengizinkan kelas parsial yang mencakup beberapa modul adalah resep bencana karena urutan pemuatan tidak dapat diprediksi. Menambahkan fitur yang hanya berfungsi dengan baik di alam semesta khusus global bukanlah penggunaan waktu yang baik.
  • C# memilikinya tetapi kami tidak di sini untuk menemukan kembali C#. Dengan serius!
  • Skenario "kode yang dihasilkan" tidak menarik pada manfaatnya. Setiap emisi yang masuk akal untuk kelas parsial akan membatasi penginisialisasi properti dan kode konstruktor ke tepat satu deklarasi, dan ini akan menjadi dealbreaker untuk pengaturan gaya .Designer.cs karena kode pengguna dan kode yang dihasilkan kemungkinan akan memerlukan inisialisasi atau logika konstruktor .
  • Ada banyak, banyak mekanisme komposisi lain yang tersedia di JS - mixin, Object.assign , dll. Skenario yang menyebabkan fitur ini di C# didorong oleh kendala yang tidak ada di JS.
  • Solusi saat ini interface + prototype.method = ... tidak memungkinkan skenario yang dihasilkan-kode sama seperti partial class akan. Aneh untuk menulis kode itu dengan tangan tetapi tidak ada masalah untuk menghasilkan kode secara berbeda, jadi jika Anda benar-benar berpikir pengaturan kode yang dihasilkan file terpisah adalah satu-satunya cara untuk menyelesaikan masalah Anda (saya skeptis) maka metode itu tersedia untuk Anda .
  • Kami menganggap ES6 sebagai penengah "harus memiliki" untuk kelas. Tidak ada yang istimewa tentang TypeScript (selain daya tariknya bagi programmer C#) yang membuatnya membutuhkan kelas parsial lebih dari JavaScript yang tidak diketik. Jadi, jika ada beberapa skenario yang benar-benar tidak memungkinkan untuk menambahkan sebagian kelas, maka skenario itu harus dapat membenarkan dirinya sendiri melalui proses TC39. Jika itu mendapatkan daya tarik, kami akan dengan senang hati mempertimbangkannya dengan masukan tentangnya, tetapi ini bahkan tampaknya tidak ada dalam radar siapa pun.

@RyanCavanaugh tentang ini:

Solusi saat ini dari interface + prototype.method = ... tidak mengaktifkan skenario kode yang dihasilkan seperti halnya kelas parsial.

Seperti yang telah saya sebutkan lebih dari sekali, saya baik-baik saja dengan ada cara non-parsial, non-c# untuk mencapai apa yang saya butuhkan, dan hanya meminta contoh kerja. david-driscoll sangat membantu, tetapi memposting kode yang tidak dapat dikompilasi. Jadi, jika Anda pikir saya dapat membuat kode untuk menghasilkan kelas dengan properti skalar hanya untuk, misalnya, nama depan, nama belakang -- seperti di atas -- tidak apa-apa. Saya hanya perlu cara untuk menambahkan koleksi jenis lain sebagai properti di kelas dengan mengkodekan tangan itu. Tetapi saya juga membutuhkan cara untuk menangani inisialisasi set itu.

@cosmoKenney apakah situs Anda menyalin kode yang benar? Contoh kedua memiliki antarmuka alih-alih nama kelas yang sama. Saya dapat melampirkan kode pos jika Anda mau. Saya hanya ragu karena file acak di internet bisa jadi buruk dan tidak ingin Anda mengira saya memposting sesuatu yang berbahaya

Maaf mendengarnya, tapi saya menghormati keputusan desain yang dibuat di sini. Saya punya beberapa pertanyaan jika itu baik-baik saja:

TypeScript sudah memiliki terlalu banyak fitur kelas khusus TS (deklarasi properti konstruktor, penginisialisasi anggota, dekorator yang belum selesai, pengubah akses, implementasi, dll.) untuk sesuatu yang sebenarnya dimaksudkan sebagai "ES6 + Types". Bagian dari itu adalah kesalahan kami (arah desain asli kami umumnya terlalu OOP) dan bagian dari itu adalah kesalahan ES6 (proposal kelas banyak berpindah-pindah lima tahun yang lalu dan kami akhirnya memiliki fitur yang tidak berhasil). Menambahkan fitur kelas khusus TS lainnya adalah hal lain di punggung unta yang harus kita hindari jika kita bisa.

Mempertimbangkan hal ini, akankah jalan ke depan yang mungkin untuk membedakan dengan jelas, secara organisasi dan kode, antara pengetikan murni JS, dan konstruksi bahasa lain yang ditawarkan TS? Saya menyukai fitur pengetikan dan bahasa tambahan. Sebagai konsumen/pengembang, saya tidak terlalu peduli dengan fakta bahwa TS menambahkan hal-hal yang tidak ada di JS. Beri saja saya barang-barang yang luar biasa, jika TC39 tidak menginginkannya, saya tidak peduli.

Jika TS akan merangkum hal-hal ini satu sama lain, mungkin itu akan lebih mudah untuk digunakan kembali dan bercabang dan dibangun di atas proyek seperti SoundScript, daripada diganti?

Dan kemudian proyek lain dapat membangun pengetikan ini untuk memberikan konstruksi bahasa yang lebih baik/lain daripada yang ditawarkan oleh JS.

Jelas, masa depan JavaScript adalah modul. Kelas parsial hanya masuk akal dan beroperasi dengan baik dalam model "sup global". Mengizinkan kelas parsial yang mencakup beberapa modul adalah resep bencana karena urutan pemuatan tidak dapat diprediksi. Menambahkan fitur yang hanya berfungsi dengan baik di alam semesta khusus global bukanlah penggunaan waktu yang baik.

Apakah itu benar-benar? Yakin bahwa modul akan menjadi bagian alami dari JavaScript, tetapi bagaimana dengan bagian utama kode asli? Saya suka namspaces dan tidak ada sup di dalamnya jika dilakukan dengan benar. Saya mengkompilasi semuanya menjadi satu file, dan saya tidak memerlukan pemuat modul dan dalam hampir semua kasus tidak perlu memuat modul asinkron. Beberapa hal yang diusulkan seperti https://github.com/Microsoft/TypeScript/issues/420 hanya akan mungkin dan relevan dengan ruang nama. Apakah Anda mengatakan bahwa hal-hal seperti ini tidak akan terjadi karena kita seharusnya hanya menggunakan modul? Apakah ruang nama di jalan menuju penghentian?

@david-driscoll Terima kasih, Anda sudah cukup membantu. Karena @RyanCavanaugh adalah orang yang terus menutup masalah dan menyatakan bahwa ada penyelesaian, mungkin dia harus memberikan contoh

Saya juga melihat banyak kesalahpahaman tentang apa itu kelas parsial. Ini benar-benar konstruksi yang sederhana, dan semua orang meniup ini di luar proporsi:
https://msdn.microsoft.com/en-us/library/wa80x488.aspx

Mempertimbangkan hal ini, akankah jalan ke depan yang mungkin untuk membedakan dengan jelas, secara organisasi dan kode, antara pengetikan murni JS, dan konstruksi bahasa lain yang ditawarkan TS? Saya menyukai fitur pengetikan dan bahasa tambahan. Sebagai konsumen/pengembang, saya tidak terlalu peduli dengan fakta bahwa TS menambahkan hal-hal yang tidak ada di JS. Beri saja saya barang-barang yang luar biasa, jika TC39 tidak menginginkannya, saya tidak peduli.

Itu akan menjadi penulisan ulang bahasa dan memecahkan kode semua orang.

Juga "Beri saya hal-hal yang luar biasa" pada dasarnya sangat berbeda dari tujuan desain untuk TypeScript . Jika Anda hanya menginginkan hal-hal yang luar biasa dan tidak peduli dengan penyelarasan dengan JavaScript, Anda harus memilih bahasa yang berbeda, seperti CoffeeScript , Dart , atau Haxe . Tentu saja mungkin ada alasan mengapa itu tidak sebaik TypeScript dalam adopsi ...

orang yang terus menutup masalah dan menyatakan bahwa ada pekerjaan di sekitar, mungkin dia harus memberikan contoh penyelesaiannya

Ada banyak kasus penggunaan yang dipecahkan oleh partial . Hampir semua konstruksi bahasa memiliki banyak kasus penggunaan yang valid, tetapi untuk alasan yang baik, Anda harus memilih dan memilih.

Anda terus meminta fitur bahasa tertentu, seperti dalam "Saya ingin mobil hijau" tetapi tidak sampai ke inti masalah, mengapa mobil harus hijau? Jika Anda menjelaskan mengapa mobil Anda harus hijau, atau terbuka pada kenyataan bahwa Anda sebenarnya tidak peduli apa warna mobil Anda, selama itu memenuhi kebutuhan Anda yang sebenarnya.

Saya tidak mengerti mengapa Anda merasa Ryan berkewajiban untuk memberi tahu Anda cara mengecat ulang mobil Anda, hanya karena untuk alasan yang sah perusahaan mobil telah memutuskan untuk tidak memproduksi mobil ramah lingkungan.

(Oh dan kelas mixin yang ditambahkan dalam TypeScript 2.2 adalah cara yang baik untuk mencapai apa yang saya duga adalah kebutuhan Anda yang sebenarnya)

interface Base {}

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

interface PartialClass {
    foo(): void;
}

function PartialClass<B extends Constructor<Base>>(base: B): B & Constructor<PartialClass> {
    return class extends base {
        foo() {
            console.log('foo');
        }
    };
}

class MyBase {
    bar() {
        console.log('bar');
    }
}

const MyPartialBase = PartialClass(MyBase);

const instance = new MyPartialBase();

instance.bar();
instance.foo();

@kitsonk mixin bukanlah hal yang sama.

  • Mixin adalah unit mandiri yang dapat ditambahkan ke kelas yang ada.
  • Kelas parsial dapat mengakses anggota dari parsial lainnya, seolah-olah mereka adalah bagian dari kelas yang sama.

Sebagai latihan, coba terapkan pembagian kode berikut dengan mixin:

partial class Point {
  readonly x: number;
  readonly y: number;
}

partial class Point {
  translate(dx: number, dy: number): Point {
    return new Point(this.x + dx, this.y + dy);
  }
}

Sebagai latihan, coba terapkan pembagian kode berikut dengan mixin

Jadi kembali ke intinya... Jadi, alih-alih menunjukkan fitur bahasa, masalah apa yang Anda coba atasi dengan contoh Anda? Karena solusi dalam TypeScript mudah:

class Point {
  readonly x: number;
  readonly y: number;
  translate(dx: number, dy: number): Point {
    return new Point(this.x + dx, this.y + dy);
  }
}

(dan jika kami komplet, tetapi sekali lagi, ini menyelesaikan suatu penggunaan, tidak semua kasus penggunaan)

interface PointBase {
    x: number;
    y: number;
}

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

interface TranslatePointPartial {
    translate(dx: number, dy: number): TranslatePointPartial;
}

function TranslatePointPartial<B extends Constructor<PointBase>>(base: B): B & Constructor<TranslatePointPartial> {
    return class TranslatePointPartial extends base {
        translate(dx: number, dy: number): TranslatePointPartial & PointBase {
            return new TranslatePointPartial(this.x + dx, this.y + dy);
        }
    };
}

class Point {
    readonly x: number;
    readonly y: number;
}

const MyPoint = TranslatePointPartial(Point);

const instance = new MyPoint();

instance.x;
instance.y;
instance.translate(1, 2);

@Gajah-Kapal

Mempertimbangkan hal ini, akankah jalan ke depan yang mungkin untuk membedakan dengan jelas, secara organisasi dan kode, antara pengetikan murni JS, dan konstruksi bahasa lain yang ditawarkan TS?

Saya tidak melihat cara untuk mengurai keduanya pada saat ini. Secara teori, seseorang dapat menulis beberapa bahasa ala CoffeeScript yang secara sintaksis diubah menjadi TypeScript dan menggunakan bahasa tingkat tinggi itu untuk menambahkan fitur sintaksis baru saat masih menggunakan sistem tipe TS, tetapi itu hanya akan membantu Anda sejauh ini. Hanya memilih salah satu dari banyak bahasa kompilasi-ke-JS greenfield lainnya sepertinya merupakan pilihan yang lebih baik jika itu tujuannya.

Apakah Anda mengatakan bahwa hal-hal seperti ini tidak akan terjadi karena kita seharusnya hanya menggunakan modul? Apakah ruang nama di jalan menuju penghentian?

Ruang nama tidak akan kemana-mana, pasti. Mereka hanyalah penamaan pola yang sudah digunakan secara luas dan masih masuk akal di dunia modul ES6. Modul semakin menjadi cara orang mengatur kode mereka dan mereka memiliki banyak manfaat sampingan yang luar biasa. Saya hanya mengatakan bahwa sebagian kelas hampir tidak masuk akal di dunia itu, dan akan aneh untuk menambahkan pola organisasi baru yang secara fundamental tidak sesuai dengannya. Jika dunia bergerak ke arah yang berlawanan dan semua orang seperti "Skrip global dengan efek samping yang dimuat luar biasa, semua orang berpesta prototype s", mungkin kita akan merasa berbeda.

@RyanCavanaugh

Mungkin begitu... Mungkin mereka tidak masuk akal... Tapi seperti yang telah saya katakan berkali-kali, saya pikir bahkan di utas ini, sebagian kelas adalah tentang membuat pembuatan kode lebih mudah... Itulah manfaat utama yang saya lihat dari mereka layak fitur di TS ... Saya, dan saya harus mengasumsikan banyak orang lain tapi itu hanya menebak, saat ini saya menghasilkan banyak kode TS dari kode C # saya ... Tapi kemudian pertanyaannya menjadi bagaimana aman memperpanjang yang dihasilkan kode TSnya??? Ini adalah pertanyaan yang jauh lebih mudah dijawab dengan kelas parsial... Saat ini kami menggunakan peretasan untuk menyimpan kode khusus dalam file kode TS yang kami buat...

Terima kasih

Hal yang sama di sini, kami membuat "proxy" TypeScript untuk C# API kami, dan kami ingin dapat memperluas objek ini dalam TypeScript dengan mudah.

Saya bukan spesialis JS jadi saya pasti melewatkan sesuatu, karena, saya tidak mengerti mengapa dapat membagi deklarasi kelas dalam beberapa file TS (dengan hanya satu deklarasi kelas hanya dalam satu file JS setelah kompilasi) akan menjadi masalah bagi dunia JS. Sejauh yang saya lihat, itu transparan untuk JS, seolah-olah itu akan ditulis dalam satu file dari awal. Maksud saya, jika Anda menggunakan kelas parsial atau tidak, output JS akan sama persis, tetapi itu akan mencegah biaya ekstensibilitas objek JS untuk pengembang kami.

@RyanCavanaugh

Satu hal lagi yang ingin saya sebutkan bahwa secara pribadi saya tidak meminta kompiler TS untuk entah bagaimana memecahkan dilema pengemasan yang mungkin timbul saat membuat modul ES6 menggunakan kelas parsial dalam file TS yang berbeda... Masuk akal bagi saya setidaknya untuk kompilasi beberapa file TS ke dalam satu file js untuk modul ES6... Sekali lagi, kelas parsial membantu pembuatan kode secara signifikan... Mereka memungkinkan perkakas untuk membuat sebagian besar model Anda dengan ekstensibilitas yang andal...

@kitsonk

Anda terus meminta fitur bahasa tertentu, seperti dalam "Saya ingin mobil hijau" tetapi tidak sampai ke inti masalah, mengapa mobil harus hijau? Jika Anda menjelaskan mengapa mobil Anda harus hijau, atau terbuka pada kenyataan bahwa Anda sebenarnya tidak peduli apa warna mobil Anda, selama itu memenuhi kebutuhan Anda yang sebenarnya.

Tidak, saya tidak meminta fitur baru lagi. Telah dinyatakan berulang kali bahwa bahasa dapat mencapai apa yang saya inginkan. Saya telah memberikan contoh apa yang saya inginkan (dalam C #), tetapi saya belum melihat dalam contoh yang bermanfaat cara untuk sampai ke tempat yang saya inginkan.

Saya tidak mengerti mengapa Anda merasa Ryan berkewajiban untuk memberi tahu Anda cara mengecat ulang mobil Anda, hanya karena untuk alasan yang sah perusahaan mobil telah memutuskan untuk tidak memproduksi mobil ramah lingkungan.

Ryan tampaknya menjadi moderator di sini dan menutup masalah. Itu sebabnya. Jika dia adalah otoritas bahasa, maka mungkin dia tidak harus menutup masalah sebelum berusaha memahami kebutuhan saya dan menolak permintaan ini tanpa memberikan contoh bagaimana melakukannya dengan fitur bahasa asli. Saya telah menyatakan bahwa saya menginginkan solusi waktu kompilasi. Dan saya seorang pengembang yang cukup baik dan telah ada untuk sementara waktu pemrograman dalam banyak bahasa yang berbeda dan tidak jelas, dan saya masih memiliki waktu yang sangat sulit dengan sintaks mixin. Saya tidak mengerti bagaimana sesuatu yang rumit dan sulit dipahami masuk ke dalam bahasa, namun semua orang menolak keanggunan sintaksis kelas parsial, tampaknya, karena dipinjam dari C#.

Ryan tampaknya menjadi moderator di sini dan menutup masalah. Itu sebabnya. Jika dia adalah otoritas bahasa, maka mungkin dia tidak harus menutup masalah sebelum berusaha memahami kebutuhan saya

🤔

@RyanCavanaugh , saya tahu Anda telah berusaha membantu. Dan pada titik ini saya melanjutkan untuk mencoba mixin. Atau hanya warisan, atau mungkin saya sedang terburu-buru untuk menyelesaikan proyek ini sehingga saya mengabaikan cara untuk melakukan ini dengan obat generik. Hmm...
Dengan pewarisan dan penamaan, saya dapat melakukan:

class AddressBase // this is a code generated class
{
    public address: string;
    public city: string;
    public state: string;
    public zip: string;

    constructor( jsonFromService: any )
    {
        this.OnInit( jsonFromService );
    }

    OnInit( jsonFromService: any )
    {
        // could use Object.assign here
        this.address = jsonFromService.address;
        this.city = jsonFromService.city;
        this.state = jsonFromService.state;
        this.zip = jsonFromService.zip;
    }
}

class ContactBase // this is also a code generated class
{
    public firstName: string;
    public lastName: string;

    constructor( jsonFromService: any )
    {
        this.OnInit( jsonFromService );
    }

    OnInit( jsonFromService: any )
    {
        // could use Object.assign here
        this.firstName = jsonFromService.firstName;
        this.lastName = jsonFromService.lastName;
    }
}

// classes that extend the functionality of the code generated classes:
class Address extends AddressBase // subclass simply because I don't want to have to use AddressBase all over my codebase, and then refactor if I ever extend the class
{
}

class Contact extends ContactBase
{
    public Addresses: Address[] = []; // THIS is the customization/extension that cannot be code generated.

    OnInit( jsonFromService: any )
    {
        // note that jsonFromService receives a dto with a array of address info
        super.OnInit( jsonFromService );

        for ( let addr of jsonFromService.Addresses )
        {
            this.Addresses.push( new Address( addr ) );
        }
    }
}

Dan itu bekerja dengan baik untuk saya. Itu tidak secantik dan memaksa kelas yang dihasilkan kode saya untuk memiliki nama yang tidak ingin saya gunakan dalam kode. Tapi, lagi-lagi berhasil.

Saat ini saya merasa bahwa orang-orang, yang sangat menentang kelas parsial, hanya salah memahami konsep kelas parsial, dan mereka berpikir bahwa kelas parsial adalah sesuatu yang bukan kelas parsial.

Untuk memperjelas: kelas parsial adalah konstruksi sintaksis, yang memungkinkan Anda membagi definisi kelas tunggal yang sama menjadi beberapa file fisik. Kata kunci di sini adalah "sama" dan "tunggal".

Dokumentasi TypeScript memberikan definisi kelas parsial yang buruk (paragraf pertama di sini: https://www.typescriptlang.org/docs/handbook/mixins.html ).

Contoh konsep kelas parsial nyata :

File "Point.generated.ts":

partial class Point {
   readonly x: number;
   readonly y: number;
}

File "Point.codeByHand.ts":

partial class Point {
  constructor(x: number, y: number) {
      this.x = x;
      this.y = y;
  }

  translate(dx: number, dy: number): Point 
  {
      return new Point(this.x + dx, this.y + dy);
  }
}

Mereka mengkompilasi menjadi "Point.js" - dan namanya berasal dari nama kelas, bukan dari nama file:

var Point = (function () {
    function Point(x, y) {
        this.x = x;
        this.y = y;
    }
    Point.prototype.translate = function (dx, dy) {
        return new Point(this.x + dx, this.y + dy);
    };
    return Point;
}());

Mixin, ketika digunakan sebagai "kelas parsial" (dan saya sangat percaya bahwa istilah ini dalam dokumentasi disalahgunakan ) sebenarnya mewakili pewarisan berganda ( https://en.wikipedia.org/wiki/Multiple_inheritance ).

Jadi, seperti yang kita lihat, kita membahas dua alat yang berbeda: kelas parsial nyata dan pewarisan berganda. Ini adalah dua alat yang berbeda. Dan sebagai alat apa pun - mereka memiliki area aplikasinya sendiri. Dengan kata lain: seorang tukang kayu dapat menggunakan palu sebagai pengganti palu, ketika palu tidak tersedia, tetapi palu bukanlah alat yang tepat.

IMHO, diskusi ini tidak memiliki masa depan dan kita harus menghentikannya. Sementara saya masih melihat tidak ada masalah teknologi untuk kelas parsial nyata , tim benar-benar tidak ingin menerapkannya, setidaknya untuk saat ini.

Tim TS tidak ingin mengimplementasikan fitur khusus TS jika memungkinkan. Jika Anda ingin berdiskusi lebih lanjut, inilah tempat yang lebih baik: https://esdiscuss.org/topic/class-syntax-enhancements

Saya harap ada repo GitHub di sisi TC39 untuk membahas hal ini daripada yang berbasis surat :/

@greendimka

Saat ini saya merasa bahwa orang-orang, yang sangat menentang kelas parsial, hanya salah memahami konsep kelas parsial, dan mereka berpikir bahwa kelas parsial adalah sesuatu yang bukan kelas parsial.

Untuk memperjelas: kelas parsial adalah konstruksi sintaksis, yang memungkinkan Anda membagi definisi kelas tunggal yang sama menjadi beberapa file fisik. Kata kunci di sini adalah "sama" dan "tunggal".

Saya tidak berpikir ada orang di sini yang salah paham definisi kelas parsial, saya pikir Anda mungkin salah paham definisi kelas dalam JavaScript.

Jika Anda mendapat kesan bahwa kelas JavaScript sama sekali seperti kelas yang ditemukan di hampir semua bahasa lain yang banyak digunakan, maka mungkin _tampak_ kepada Anda bahwa orang lain salah paham.

Namun, seperti yang telah dikatakan berkali-kali dalam diskusi ini, saya tahu saya telah mengatakannya secara eksplisit setidaknya sekali, kelas JavaScript bukanlah konstruksi deklaratif, mereka sangat penting.

Mereka tidak ada sampai pernyataan dieksekusi.

Mendefinisikan mereka bergantung pada mutasi.

Ini sudah membuat mereka rapuh dan bergantung pada ketertiban dalam hal warisan.

Ini bisa terus dan terus...

@cosmoKenney

Saya tidak mengerti bagaimana sesuatu yang rumit dan sulit dipahami masuk ke dalam bahasa, namun semua orang menolak keanggunan sintaksis kelas parsial, tampaknya, karena dipinjam dari C#.

Saya benar-benar tidak berpikir itu benar. Semua orang menyukai C#, bahkan programmer Java , dan TypeScript tidak berbeda demi menjadi berbeda.

@aluanhaddad

Saya pikir Anda mungkin salah memahami definisi kelas dalam JavaScript ...

Untuk dikutip dan di bawah: Saya berbicara tentang TypeScript.
Seperti yang saya katakan: Saya tidak melihat masalah teknis dalam mengimplementasikan kelas parsial nyata di TypeScript, yang akan dikompilasi ke dalam konstruksi JavaScript.

@greendimka

Untuk dikutip dan di bawah: Saya berbicara tentang TypeScript.
Seperti yang saya katakan: Saya tidak melihat masalah teknis dalam mengimplementasikan kelas parsial nyata di TypeScript, yang akan dikompilasi ke dalam konstruksi JavaScript.

Masalah dengan satatement ini tidak ada yang namanya kelas TypeScript.

Oh Boy! Beberapa orang akan menggunakan apapun sebagai alasan.
Oke, tidak ada kelas di TypeScript. Atau kelas TypeScript. Atau terserah. Apa pun.

Maksud saya mereka adalah kelas JavaScript. Meskipun terkadang saya bersalah karena terlalu bertele-tele, saya secara khusus membuat perbedaan ini karena kita perlu menyepakati definisi istilah kelas sebelum kita dapat mendiskusikan fitur apa yang mudah ditambahkan ke dalamnya.

Saya pikir kita tidak bermaksud hal yang sama ketika kita berbicara tentang kelas dan itu menyebabkan disonansi kognitif dan menghambat saling pengertian.

Saya pikir kita tidak bermaksud hal yang sama ketika kita berbicara tentang kelas dan itu menyebabkan disonansi kognitif dan menghambat saling pengertian..
Setuju!

Sebenarnya posting pertama dalam topik ini dengan sempurna menggambarkan apa yang diminta, oleh karena itu diskusi ini tidak memiliki masa depan :)

@greendimka ya, itu tidak memiliki masa depan karena sepertinya TypeScript tidak akan pernah memiliki kelas parsial. Dalam pandangan saya, itu adalah hal yang baik.

Namun, kesalahpahaman dan miskomunikasi bukanlah hal yang baik, itulah sebabnya saya masih berbicara dengan Anda.

Sayangnya, Anda tampaknya juga tidak tertarik

A. Menjelaskan apa itu JavaScript adalah kelas sehingga orang mungkin berubah pikiran dan setuju dengan Anda bahwa mereka dapat dengan mudah dibuat parsial.

B. Belajar dari orang lain tentang apa itu kelas JavaScript sehingga Anda harus memahami sudut pandang yang berlawanan.

Saya pikir ini memalukan, tetapi saya tidak akan membahasnya lebih lanjut jika Anda menginginkannya.

Saya tidak menentang diskusi apa pun. Tetapi telah dinyatakan beberapa kali di sini bahwa sebagian kelas tidak akan dilaksanakan (setidaknya tidak sekarang). Jadi saya pikir lebih baik berkonsentrasi pada hal-hal lain. Mungkin TypeScript bisa diubah di masa depan, siapa tahu.
Sehubungan dengan A dan B. Saya benci JavaScript. Tapi saya tahu betul dan, tentu saja, saya tahu bagaimana kelas "diwakili" di dalamnya. Tetapi inti dari seluruh diskusi ini bukanlah untuk memodifikasi JavaScript, tetapi untuk meningkatkan kemampuan TypeScript, sebagai bahasa yang lebih tinggi, yang menghasilkan kode JavaScript "tingkat rendah".
Bayangkan kita akan mengganti TypeScript dengan C++ dan JavaScript dengan kode mesin. Kode mesin tidak memiliki sebagian besar konsep yang ada di C++. Tetapi haruskah C++ berhenti berkembang karena itu? Tentu tidak. Haruskah berhenti berkembang karena beberapa kompiler lama tidak dapat dikompilasi? Tentu saja tidak - Anda memberikan fitur baru kepada pengembang dan memberi tahu mereka: fitur ini berfungsi dengan kompiler baru - Anda (pengembang) memutuskan apakah Anda ingin menggunakannya.

@aluanhaddad
Laki-laki oh manusia. Siapa yang peduli dengan bagian Javascript dari persamaan? TypeScript adalah lapisan di atas, atau bagaimanapun Anda ingin mengungkapkannya. Ingat diskusi 4GL vs 3GL lama? TypeScript untuk Javascript sebagai 4GL adalah untuk 3GL, semacam. Juga argumen bahwa TypeScript adalah ES6 dengan tipe yang kuat, sehingga Kelas Parsial berada di luar cakupan peta jalan TypeScript adalah LAME. Kami mendapat Mixin, Generics, Modules, Name Spaces, dan Type Casting. Jadi mengapa tidak bekerja ekstra dengan Kelas Parsial?

Yang kami inginkan dari kelas parsial adalah gula sintaksis yang memungkinkan kami untuk menggabungkan semua berbagai definisi dari satu kelas TypeScript menjadi satu final - level rendah - 3GL - definisi kelas Javascript. Seharusnya tidak ada dampak pada definisi akhir kelas JavaScript, bukan? Mengapa produk akhir dari transpilasi ke Javascript bahkan menjadi bagian dari diskusi ini? Dengan serius.

@cosmoKenney "hanya ES.berikutnya dengan tipe" adalah nilai jual besar yang mengubah pengembang JavaScript. Jika Anda menginginkan sesuatu yang lebih, Anda melihat bahasa yang salah. Mungkin coba Scala.js saja?

edit: Saya baru saja menyadari bahwa di ES.next sebagian kelas dapat diimplementasikan dengan pemuat modul khusus. Jika Anda menggunakan

import {MyClass} from './myclass.*'

loader dapat menggabungkan semua definisi MyClass yang diekspor dari file apa pun yang cocok dengan wildcard ke dalam satu kelas, lalu menyediakannya.

@spion Saya suka bagaimana Anda menyebut mereka dengan benar sebagai kelas parsial ES. Pemuat modul ES, seperti browser, atau polyfill pemuat, seperti SystemJS, kemudian akan mendukung kelas parsial.
Salah satu masalah utama dengan menambahkan fitur ini pada tingkat TypeScript adalah bahwa hal itu merusak alat yang ada seperti loader dan packager. Di sisi lain, jika ECMAScript menentukannya, maka semua alat ini akan mengimplementasikan fitur dan TypeScript akan tetap kompatibel dengan semua alat ini.

Saya sangat setuju dengan Anda mengenai Scala.js

@cosmoKenney

Kami mendapat Mixin, Generics, Modules, Name Spaces, dan Type Casting. Jadi mengapa tidak bekerja ekstra dengan Kelas Parsial?

Mixin seperti yang terlihat di TypeScript adalah pola desain ECMAScript yang TypeScript _types_.

Generik adalah fitur sistem tipe sehingga tidak berlaku.

Modul adalah fitur ECMAScript.

Namespaces adalah gula sintaksis dan formalisasi pola desain ECMAScript.

Jenis Casting tidak ada di TypeScript.

@aluanhaddad mengapa Anda terus menjadikan ini sebagai run-time? Pemuat modul dan semua yang tidak ada hubungannya dengan transpiling.

+1

@cosmoKenney

@aluanhaddad mengapa Anda terus menjadikan ini sebagai run-time? Pemuat modul dan semua yang tidak ada hubungannya dengan transpiling.

Itu tidak benar.

Lihatlah ekosistem SystemJS dan Webpack dan Anda akan melihat sebaliknya.

Bahkan lebih tradisional, dan alur kerja tegukan yang solid bergantung pada korespondensi antara file input dan output.

+1

Saya membutuhkan kelas parsial karena kami menghasilkan sebagian besar kelas dasar menggunakan alat (untuk mengotomatisasi ketika ada perubahan dalam model). Kami kemudian menggunakan kelas parsial untuk menambahkan fungsionalitas ke kelas dalam file terpisah sehingga tidak akan ditimpa oleh alat (yang menghasilkan kelas secara otomatis).

Apakah halaman ini membantu?
0 / 5 - 0 peringkat