object
Proposal ini menjelaskan tipe primitif baru untuk skrip ketikan object
.
Api inti JavaScript berisi beberapa fungsi yang menggunakan object
sebagai parameter:
Object.getPrototypeOf
Object.getOwnPropertyDescriptor
Object.create
Saat ini tidak ada cara dalam skrip ketikan untuk mencegah penerusan tipe primitif lainnya ( string
, number
, dll ...) ke fungsi tersebut.
Misalnya Object.create('string')
adalah pernyataan ketikan yang benar-benar valid, bahkan jika itu akan berakhir dengan kesalahan.
Membuat tipe primitif object
akan memungkinkan untuk memodelkan tanda tangan fungsi tersebut dengan lebih tepat, dan setiap fungsi yang memiliki batasan serupa.
Jenis object
setara dengan {}
dikurangi penetapan jenis dasar lainnya, yang berarti bahwa:
object
object
{}
dan any
Perilaku ini koheran dengan cara kerja javascript, tipe mewakili setiap nilai yang menghormati batasan typeof value === 'object'
plus undefined
.
Penjaga tipe baru harus diperkenalkan seharga object
: typeof value === 'object'
.
Secara opsional, kompilator juga dapat menerima perbandingan dengan fungsi Object
cast: Object(value) === value
.
Akan berguna untuk membuat daftar beberapa API selain fungsi Object.
yang akan mendapatkan keuntungan dari ini.
Dalam api inti javascript kecuali dari Object
hanya mungkin beberapa konstruksi es6 akan mendapatkan keuntungan dari ini (WeakMap, Proxy dll).
Tetapi misalnya setiap fungsi koleksi garis bawah juga akan mendapatkan pengetikan yang lebih baik, kerangka kerja seperti React menggunakan metode 'setState' yang hanya menerima objek atau null
, ImmutableJS, Mori dll.
Edit: koleksi garis bawah bekerja dengan semua jenis
Dibahas pada pertemuan tinjauan saran. Ini semua masuk akal, tetapi kita perlu menjustifikasi kompleksitas tipe primitif baru dengan jumlah kesalahan / kekayaan deskripsi yang dapat diberikannya. Pada dasarnya, lebih banyak contoh API yang tidak dapat beroperasi pada primitif, terutama yang bukan API "ahli" (mis. Proxy)
Posting lebih banyak sebagai referensi daripada rekomendasi: wink:
interface String { _primitiveBrand?: string; }
interface Boolean { _primitiveBrand?: boolean; }
interface Number { _primitiveBrand?: number; }
interface ObjectOnly { _primitiveBrand?: void; }
function fn(x: ObjectOnly) { }
// Error
fn(43);
// Error
fn('foo');
// OK
fn({});
// OK
fn(window);
+1 pada proposal ini. Saya tidak akan menganggap WeakMap
sebagai API "ahli", tetapi saya menganggapnya sebagai alasan yang cukup untuk mengimplementasikan ini. Karena runtime membuat perbedaan antara tipe objek dan tipe primitif, masuk akal untuk memiliki fasilitas di TypeScript untuk membuat perbedaan juga.
Proposal ini juga akan memecahkan masalah pengetikan "tas objek" di mana setiap properti bersifat opsional, tetapi jenis primitif lainnya harus dilarang.
Object.observe
membutuhkan target non-primitif juga: http://arv.github.io/ecmascript-object-observe/#Object.observe
Saya rasa judulnya agak membingungkan karena menyebutkan kata "primitif". Ini juga bisa disebut _ "Jenis objek ECMAScript" _ atau _ "Jenis objek waktu proses" _. Yang akan dapat ditetapkan dari apa pun selain tipe primitif (termasuk undefined
tipe dan simbol), fungsi atau tipe konstruktor. Kriteria untuk jenis object
legal harus didasarkan pada penjaga berikut:
let isObject (x) => typeof x === "object";
Menurut MDN , ini adalah keluaran dari typeof
:
Belum ditentukan: "tidak ditentukan"
Null : "object" (lihat di bawah)
Boolean : "boolean"
Nomor : "number"
String : "string"
Simbol (baru di ECMAScript 2015) : "simbol"
Objek host (disediakan oleh lingkungan JS) : Tergantung pada implementasi
Objek fungsi (mengimplementasikan [[Call]] dalam istilah ECMA-262) : "function"
Objek lainnya : "object"
Tanpa tipe ini, tidak ada cara untuk mencocokkan tipe tepat dengan tepat untuk penjaga yang disebutkan di atas, bahkan sebagai penjaga yang ditentukan pengguna. Ini juga penting untuk digunakan dengan fungsi apa pun yang benar-benar membutuhkan objek yang memiliki properti dan memungkinkan for in
loop dan panggilan ke prototipe Object
, dan untuk mengimplementasikan batasan umum seperti T extends object
dan kemudian mereferensikan properti atau menggunakan fungsi prototipe dengan aman.
Namun, memiliki fungsi dan konstruktor yang dikecualikan akan menjadi sedikit membatasi dalam beberapa kasus, jadi mungkin ada tipe lain yang akan menyertakannya juga dan disebut _ "tipe objek non-primitif" _. Solusi parsial dapat berupa gabungan object | Function
meskipun pemeran atau penjaga tambahan diperlukan untuk menanganinya dengan benar.
Menerima PR. Ini tampaknya menjadi masalah umum; ini akan menjadi perubahan besar bagi siapa pun yang cukup berani untuk menulis interface object { ... }
. Penerapannya harus langsung dan mengikuti aturan yang diuraikan di atas.
Catatan tambahan: Kami semua bertanya-tanya di mana @fdecampredon berada!
@RyanCavanaugh Pindah kota kerja, dan sayangnya tidak banyak ketikan di pekerjaan baru saya: D
Bagus. Saya ingin menggunakan tipe ini di TS1.8.
Saya juga ingin melihat sesuatu seperti tipe object
. Namun, saya mempertanyakan apakah itu harus sesuai dengan typeof value === 'object'
, karena ini akan mengecualikan fungsi. Alih-alih, menurut saya tipe prospektif object
harus mencerminkan tipe bahasa Object, yang menyertakan fungsi. Ada beberapa alasan untuk ini:
Object
.Saya akan mengambil ini secara berurutan.
API seperti WeakMap
yang hanya menerima objek menerima tipe bahasa Objek, bukan hanya objek biasa. Berikut ini tidak masalah:
function theAnswer() {}
let map = new WeakMap();
map.set(theAnswer, 42);
console.log(map.get(theAnswer)); // 42
Ini berlaku untuk API khusus seperti untuk API bawaan. Jika saya mengharapkan sebuah objek, saya biasanya hanya menginginkan sekumpulan properti. Fungsi hanyalah kumpulan properti yang dapat dipanggil.
Karena Function
memperluas konstruktor Object
, kita dapat menggunakan metode statis dan contoh yang tersedia pada Object
pada fungsi juga. Misalnya, berikut ini mungkin:
class DeepThought {
static getAnswer() {
return 42;
}
}
let computer = Object.create(DeepThought);
console.log(computer.getAnswer()); // 42
console.log(Object.getPrototypeOf(computer)); // [Function: DeepThought]
Meskipun contoh di atas agak konyol, ini hanya menggambarkan bahwa API yang menggunakan metode Object
internal juga dapat menerima fungsi.
Jadi saya akan menyarankan bahwa tipe object
sesuai dengan yang berikut, yang sesuai dengan tipe bahasa Objek (kecuali bahwa itu termasuk null
, tetapi tidak ada perlindungan terhadap null
dalam TypeScript dalam hal apapun).
function isObject(value) {
return typeof value === 'object' || typeof value === 'function';
}
Saya memiliki proyek bernama Deep Map yang berulang melalui pasangan nilai kunci dari objek bersarang dan mengubah nilai primitif di sepanjang jalan. Dengan demikian, ini membedakan antara tipe primitif dan non-primitif. Saya harus menentukan antarmuka khusus NonPrimitive
, sebagai berikut:
interface NonPrimitive {
[key: string]: any;
[index: number]: any;
}
export class DeepMap {
// ...
private mapObject(obj: NonPrimitive): NonPrimitive { /* ... */ }
}
Ini bukan pertama kalinya saya harus mendefinisikan antarmuka NonPrimitive
. Alangkah baiknya jika saya bisa melakukan ini:
export class DeepMap {
// ...
private mapObject(obj: object): object { /* ... */ }
}
Seperti yang saya sarankan di atas, saya tidak terlalu peduli apakah parameter obj
dapat dipanggil atau tidak. Yang penting adalah bahwa ini adalah dari Object
_language type_, yaitu, bahwa itu adalah bundel properti yang pasangan key-value-nya dapat saya lakukan iterasi.
Saya setuju bahwa fungsinya adalah object
s. Tujuannya adalah untuk mengecualikan primitif.
Oke, saya pikir itu pasti niatnya. Saya hanya berpikir mungkin saya melewatkan sesuatu dengan semua pembicaraan tentang typeof value === 'object'
.
apakah object
type ini memungkinkan penetapan properti ad-hoc (seperti any
)? Sebagai contoh:
const foo: object = {};
foo.bar = 'baz';
Tidak
Apa perbedaan praktis antara
export class DeepMap {
// ...
private mapObject(obj: object): object { /* ... */ }
}
dan
export class DeepMap {
// ...
private mapObject(obj: Object): Object { /* ... */ }
}
? (Menggunakan object
vs Object
). Menurut saya, Function
berasal dari Object
, jadi saya tidak mengerti mengapa kita belum bisa melakukannya. Bisakah Anda menjelaskan?
@trusktr Semua nilai selain null
dan undefined
dapat dialihkan ke tipe Object
; fungsi yang menerima Object
akan mengambil string, angka, boolean, atau simbol. Hanya nilai non-primitif yang dapat ditetapkan ke object
; melewatkan string, dll, akan menghasilkan kesalahan waktu kompilasi. Tipe object
berguna ketika kita mengharapkan nilai non-primitif, tetapi kita tidak peduli apa propertinya.
Komentar yang paling membantu
+1 pada proposal ini. Saya tidak akan menganggap
WeakMap
sebagai API "ahli", tetapi saya menganggapnya sebagai alasan yang cukup untuk mengimplementasikan ini. Karena runtime membuat perbedaan antara tipe objek dan tipe primitif, masuk akal untuk memiliki fasilitas di TypeScript untuk membuat perbedaan juga.Proposal ini juga akan memecahkan masalah pengetikan "tas objek" di mana setiap properti bersifat opsional, tetapi jenis primitif lainnya harus dilarang.