Cara init kelas baru TS
sedemikian rupa (contoh C#
untuk menunjukkan apa yang saya inginkan):
// ... some code before
return new MyClass { Field1 = "ASD", Field2 = "QWE" };
// ... some code after
[Sunting]
Ketika saya menulis pertanyaan ini saya murni pengembang NET. Tanpa banyak pengetahuan JS. Juga TypeScript adalah sesuatu yang sama sekali baru, diumumkan sebagai superset berbasis C # baru dari JavaScript. Hari ini saya melihat betapa bodohnya pertanyaan ini.
Pokoknya jika ada yang masih mencari jawaban, silakan lihat solusi yang mungkin di bawah ini.
Hal pertama yang perlu diperhatikan adalah dalam TS kita tidak harus membuat kelas kosong untuk model. Cara yang lebih baik adalah dengan membuat antarmuka atau tipe (tergantung kebutuhan). Artikel bagus dari Todd Motto: https://ultimatecourses.com/blog/classes-vs-interfaces-in-typescript
SOLUSI 1:
type MyType = { prop1: string, prop2: string };
return <MyType> { prop1: '', prop2: '' };
SOLUSI 2:
type MyType = { prop1: string, prop2: string };
return { prop1: '', prop2: '' } as MyType;
SOLUSI 3 (ketika Anda benar-benar membutuhkan kelas):
class MyClass {
constructor(public data: { prop1: string, prop2: string }) {}
}
// ...
return new MyClass({ prop1: '', prop2: '' });
atau
class MyClass {
constructor(public prop1: string, public prop2: string) {}
}
// ...
return new MyClass('', '');
Tentu saja dalam kedua kasus Anda mungkin tidak perlu tipe casting secara manual karena mereka akan diselesaikan dari tipe fungsi / metode pengembalian.
sumber
return new MyClass { Field1: "ASD", Field2: "QWE" };
Jawaban:
Memperbarui
Sejak menulis jawaban ini, cara yang lebih baik telah muncul. Silakan lihat jawaban lain di bawah ini yang memiliki lebih banyak suara dan jawaban yang lebih baik. Saya tidak dapat menghapus jawaban ini karena sudah ditandai diterima.
Jawaban lama
Ada masalah pada codeplex TypeScript yang menjelaskan ini: Dukungan untuk inisialisasi objek .
Seperti yang dinyatakan, Anda sudah bisa melakukan ini dengan menggunakan antarmuka dalam TypeScript daripada kelas:
sumber
Person
, tetapi sama sekali bukan turunan dariPerson
. Bayangkan bahwaPerson
sebenarnya akan menjadi kelas dengan konstruktor yang kompleks dan banyak metode, pendekatan ini akan jatuh datar di wajahnya. Baik bahwa sekelompok orang menganggap pendekatan Anda bermanfaat, tetapi itu bukan solusi untuk pertanyaan seperti yang dinyatakan dan Anda bisa menggunakan Person kelas dalam contoh Anda alih-alih antarmuka, itu akan menjadi tipe yang sama.Diperbarui 07/12/2016: Script 2.1 memperkenalkan Jenis dan menyediakan Dipetakan
Partial<T>
, yang memungkinkan Anda untuk melakukan ini ....Jawaban asli:
Pendekatan saya adalah mendefinisikan
fields
variabel terpisah yang Anda berikan ke konstruktor. Caranya adalah mendefinisikan ulang semua bidang kelas untuk penginisialisasi ini sebagai opsional. Ketika objek dibuat (dengan default-nya), Anda cukup menetapkan objek initialiser kethis
;atau melakukannya secara manual (sedikit lebih aman):
pemakaian:
dan output konsol:
Ini memberi Anda keamanan dasar dan inisialisasi properti, tetapi semuanya opsional dan dapat rusak. Anda mendapatkan standar kelas dibiarkan sendiri jika Anda tidak lulus bidang.
Anda juga dapat mencampurnya dengan parameter konstruktor yang diperlukan juga - tetap
fields
di ujung.Tentang sedekat mungkin dengan gaya C # yang akan saya dapatkan ( sintaksis lapangan-init sebenarnya ditolak ). Saya lebih suka penginisialisasi bidang yang tepat, tetapi sepertinya belum akan terjadi.
Sebagai perbandingan, jika Anda menggunakan pendekatan casting, objek initializer Anda harus memiliki SEMUA bidang untuk tipe yang Anda casting, plus tidak mendapatkan fungsi spesifik kelas (atau derivasi) yang dibuat oleh kelas itu sendiri.
sumber
Partial<>
, hanyaPerson
- yang akan mengharuskan Anda untuk melewati objek yang memiliki bidang yang diperlukan. yang mengatakan, lihat di sini untuk ide (Lihat Pilih) yang membatasi Pemetaan Tipe untuk bidang tertentu.public constructor(init?:Partial<Person>) { Object.assign(this, init); }
Di bawah ini adalah solusi yang menggabungkan aplikasi yang lebih pendek
Object.assign
untuk lebih memodelkanC#
pola aslinya .Tapi pertama-tama, mari kita tinjau teknik yang ditawarkan sejauh ini, yang meliputi:
Object.assign
Partial<T>
Trik yang cerdik dalam copy constructorObject.create
bukannyaObject.assign
Tentu saja, masing-masing memiliki pro / kontra. Memodifikasi kelas target untuk membuat copy constructor mungkin tidak selalu menjadi pilihan. Dan "casting" kehilangan fungsi yang terkait dengan tipe target.
Object.create
tampaknya kurang menarik karena membutuhkan peta deskriptor properti yang agak verbose.Jawaban Singkat, Tujuan Umum
Jadi, inilah pendekatan lain yang agak sederhana, mempertahankan definisi tipe dan prototipe fungsi terkait, dan lebih dekat memodelkan
C#
pola yang dimaksud :Itu dia. Satu-satunya tambahan di atas
C#
pola adalahObject.assign
bersama dengan 2 tanda kurung dan koma. Lihatlah contoh kerja di bawah ini untuk mengonfirmasi bahwa ia memelihara prototipe fungsi tipe itu. Tidak diperlukan konstruktor, dan tidak ada trik pintar.Contoh Kerja
Contoh ini menunjukkan cara menginisialisasi objek menggunakan perkiraan
C#
penginisialisasi bidang:sumber
Anda dapat memengaruhi objek anonim yang dicetak dalam tipe kelas Anda. Bonus : Di studio visual, Anda mendapat manfaat dari intellisense dengan cara ini :)
Edit:
PERINGATAN Jika kelas memiliki metode, turunan kelas Anda tidak akan mendapatkannya. Jika AClass memiliki konstruktor, itu tidak akan dieksekusi. Jika Anda menggunakan instance dari AClass, Anda akan mendapatkan false.
Kesimpulannya, Anda harus menggunakan antarmuka dan bukan kelas . Penggunaan paling umum adalah untuk model domain yang dideklarasikan sebagai Plain Old Objects. Memang, untuk model domain Anda sebaiknya menggunakan antarmuka daripada kelas. Antarmuka digunakan pada waktu kompilasi untuk memeriksa jenis dan tidak seperti kelas, antarmuka sepenuhnya dihapus selama kompilasi.
sumber
AClass
berisi metode,anInstance
tidak akan mendapatkannya.anInstance instanceof AClass
Anda akan mendapatkanfalse
pada saat runtime.Saya menyarankan pendekatan yang tidak memerlukan naskah 2.1:
poin kunci:
Partial<T>
tidak wajibsumber
new Person(<Person>{});
(karena casting) dan harus jelas juga; menggunakan fungsi pendukung <T> Sebagian. Pada akhirnya, jika Anda memiliki bidang yang diperlukan (ditambah fungsi prototipe), Anda harus melakukan:init: { name: string, address?: string, age: number }
dan melepaskan pemeran.class
ituvar
, jika saya melakukannyavar dog: {name: string} = {name: 'will be assigned later'};
, itu mengkompilasi dan karya. Adakah kekurangan atau masalah? Oh,dog
memiliki cakupan yang sangat kecil dan spesifik, artinya hanya satu contoh.Saya akan lebih cenderung melakukannya dengan cara ini, menggunakan properti dan default otomatis (opsional). Anda belum menyarankan bahwa kedua bidang adalah bagian dari struktur data, jadi itu sebabnya saya memilih cara ini.
Anda dapat memiliki properti di kelas dan kemudian menetapkannya dengan cara biasa. Dan jelas mereka mungkin atau mungkin tidak diminta, jadi itu sesuatu yang lain juga. Hanya saja ini adalah gula sintaksis yang bagus.
sumber
Dalam beberapa skenario mungkin dapat diterima untuk digunakan
Object.create
. Referensi Mozilla menyertakan polyfill jika Anda memerlukan kompatibilitas kembali atau ingin menjalankan fungsi initializer Anda sendiri.Diterapkan pada contoh Anda:
Skenario yang Berguna
Dalam kasus saya, saya menemukan ini berguna dalam unit test karena dua alasan:
__proto__
) dan gagal dalam tes. Sebagai contoh:Output dari kegagalan unit test tidak akan menghasilkan petunjuk tentang apa yang tidak cocok.
Akhirnya, solusi yang diajukan di http://typescript.codeplex.com/workitem/334 tidak mendukung inline json-style declaration. Misalnya, yang berikut ini tidak dikompilasi:
sumber
Saya menginginkan solusi yang memiliki yang berikut:
Inilah cara saya melakukannya:
Semua properti di konstruktor adalah wajib dan tidak boleh dihilangkan tanpa kesalahan kompilator.
Itu tergantung pada
OnlyData
yang menyaringgetFullName()
keluar dari properti yang diperlukan dan didefinisikan seperti:Batasan saat ini dengan cara ini:
sumber
Ini adalah solusi lain:
sumber
Anda bisa memiliki kelas dengan bidang opsional (ditandai dengan?) Dan konstruktor yang menerima turunan dari kelas yang sama.
Dalam hal ini, Anda tidak akan dapat menghilangkan bidang yang diperlukan. Ini memberi Anda kontrol halus atas konstruksi objek.
Anda bisa menggunakan konstruktor dengan tipe Partial seperti yang tercantum dalam jawaban lain:
Masalahnya adalah bahwa semua bidang menjadi opsional dan tidak diinginkan dalam banyak kasus.
sumber
Cara termudah untuk melakukan ini adalah dengan tipe casting.
sumber
MyClass
?Jika Anda menggunakan naskah naskah versi lama <2.1 maka Anda dapat menggunakan yang serupa dengan yang berikut ini yang pada dasarnya melakukan pengecoran terhadap objek apa pun yang diketik:
sumber
jika Anda ingin membuat instance baru tanpa menetapkan nilai awal saat instance
1- Anda harus menggunakan kelas bukan antarmuka
2 - Anda harus menetapkan nilai awal saat membuat kelas
sumber