Typescript: Pertimbangkan untuk mengizinkan akses ke UMD global dari modul

Dibuat pada 5 Agu 2016  ·  73Komentar  ·  Sumber: microsoft/TypeScript

Umpan balik dari # 7125 adalah bahwa beberapa orang benar-benar melakukan mix and match perpustakaan UMD global dan impor, yang tidak kami anggap sebagai skenario yang mungkin terjadi saat mengimplementasikan fitur tersebut.

Tiga opsi yang masuk akal:

  1. Lakukan apa yang kita lakukan hari ini - buruk karena tidak ada solusi yang baik
  2. Izinkan beberapa sintaks atau konfigurasi untuk mengatakan "UMD global ini sebenarnya tersedia secara global" - agak rumit, tetapi dapat dilakukan
  3. Izinkan akses ke semua UMD global apa pun konteksnya - melewatkan kesalahan saat orang lupa mengimpor global UMD dalam sebuah file. Ini mungkin agak jarang, tetapi akan sangat bodoh jika melewatkannya

Sepertinya itu akan berhasil tetapi mungkin tidak akan:

  1. Tandai modul UMD yang diimpor sebagai "tidak tersedia untuk global" - buruk karena modul UMD akan diimpor dalam file deklarasi selama augmentasi modul. Akan aneh jika memiliki perilaku impor yang berbeda dari file implementasi vs file deklarasi.

Saya cenderung ke opsi 3 demi kesederhanaan, tetapi dapat melihat opsi 2 jika ada sintaks atau konfigurasi yang cukup baik yang dapat kita gunakan di tempat yang logis. Mendeteksi penggunaan UMD global dalam aturan TSLint akan sangat mudah jika seseorang ingin melakukan ini.

Satu jalan ke depan adalah dengan mengimplementasikan opsi 3 dan jika ternyata orang sering membuat kesalahan "lupa mengimpor", tambahkan opsi tsconfig globals: [] yang secara eksplisit menentukan global UMD mana yang diizinkan.

Add a Flag Committed Suggestion good first issue help wanted

Komentar yang paling membantu

+1 ini. Saya baru saja mencoba menggunakan React dengan SystemJS, dan karena React tidak digabungkan dengan baik, saya hanya memuatnya langsung dari CDN dalam tag skrip, dan dengan demikian objek React / ReactDOM tersedia secara global.

Saya menulis kode sebagai modul sebagai praktik terbaik, tetapi ini akan digabungkan (Rollup) menjadi satu skrip runtime yang dijalankan saat dimuat. Sungguh menyakitkan (dan bohong) harus import from react / react-dom, lalu konfigurasikan loader untuk mengatakan "tidak juga, ini adalah global" (mirip dengan contoh konfigurasi WebPack yang diberikan di https: / /www.typescriptlang.org/docs/handbook/react-&-webpack.html). Akan jauh lebih mudah (dan lebih akurat) untuk menyediakan ini sebagai global dalam modul saya. Langkah-langkah yang saya coba, karena tampaknya intuitif, adalah:

  1. npm install --save-dev @types/react @types/react-dom
  2. Di tsconfig.json saya: "jsx": "react", "types": ["react", "react-dom"]
  3. Dalam modul saya: export function MyComponent() { return <div>{"Hello, world"}</div>; }
  4. Demikian pula: ReactDOM.render(...)

Namun ini menghasilkan kesalahan React refers to a UMD global, but the current file is a module. Consider adding an import instead .

Jika ini berhasil, ini akan jauh lebih sederhana daripada berpura-pura dalam kode itu adalah modul, lalu mengonfigurasi loader / bundler bahwa itu bukan. (Atau sebagai alternatif, saya agak mendapatkannya untuk melakukan apa yang saya harapkan dengan menambahkan file yang berisi di bawah ini. Sekarang modul saya dapat menggunakan React & ReactDOM sebagai global tanpa kesalahan, tetapi agak jelek / hacky - meskipun mungkin ada cara yang lebih sederhana saya ' sudah terlewat):

import * as ReactObj from "react";
import * as ReactDOMObj from "react-dom";

declare global {
    var React: typeof ReactObj;
    var ReactDOM: typeof ReactDOMObj;
}

Semua 73 komentar

Daripada mengizinkan akses ke semua UMD global apa pun konteksnya, bukankah lebih sederhana untuk hanya mengizinkan akses ke global UMD jika modul UMD telah secara eksplisit "direferensikan" (tidak diimpor) baik melalui sintaks ///<reference types=<>> , atau melalui konfigurasi types di tsconfig.json?

Dengan kata lain, mengapa tidak mengizinkan ///<reference types=<>> digunakan di dalam modul?

Jika kami mengatakan /// <reference type="x" /> berarti x tersedia secara global _everywhere_, sering kali terjadi bahwa beberapa file .d.ts di suatu tempat akan salah merujuk hal-hal yang tidak benar-benar global ( Saya dapat memberi tahu Anda ini karena saya telah mempertahankan cabang 2.0 dari DefinitelyTyped dan ini adalah kesalahan yang sangat umum).

Sebaliknya jika itu hanya tersedia _ di file_ itu, maka Anda harus menyalin dan menempel arahan referensi di semua tempat, yang benar-benar menjengkelkan. Arahan ini biasanya idempoten jadi memperkenalkan perilaku khusus file itu aneh.

Saya melihat. Nah, jika ini tidak memengaruhi orang lain, mungkin lebih baik mempertahankan perilaku saat ini. Saya hanya harus beralih sepenuhnya ke mengimpor hal-hal sebagai modul.

Sunting: senang melihat ini mempengaruhi banyak orang selain saya.

Teori saat ini adalah hanya meminta orang untuk bermigrasi menggunakan modul atau tidak. Jika orang lain mengalami ini, silakan tinggalkan komentar dengan persis perpustakaan mana yang Anda gunakan sehingga kami dapat menyelidiki lebih lanjut.

Saya menggunakan lodash, yang tidak memiliki pengetikan sendiri. Saya juga memiliki situasi di mana dalam lingkungan runtime saya paling mudah menggunakan pernyataan impor jalur relatif. Jadi, saya memiliki kombinasi pernyataan impor dengan jalur relatif lokal dan kerabat folder ('./foo' serta 'N / bar').

Jika saya menyalin secara manual @types/lodash/index.d.ts ke node_modules/lodash/ saya bisa memeriksa kesalahan ketik.

Sampai sekarang solusi saya adalah menggunakan ///<amd-dependency path='../lodash' name="_"> (dan tidak ada pernyataan import ). Dengan kombo ini, definisi @ types / lodash akan dilihat 'secara global' oleh kompiler dan masih memiliki jalur relatif yang benar ( ../lodash ) di JS yang dipancarkan.

Saya harap skenario ini cukup dekat dengan masalah ini?

Bisakah Anda menjelaskan

Saya juga memiliki situasi di mana dalam lingkungan runtime saya paling mudah menggunakan pernyataan impor jalur relatif.

dan

Jika saya menyalin secara manual @types/lodash/index.d.ts ke node_modules/lodash/ saya bisa memeriksa kesalahan ketik.

silahkan? Saya tidak terbiasa dengan skenario ini, jadi apa tujuan dari ini dan mengapa ini membantu?

Hai kawan,

Saya sedang dalam proses mencari solusi untuk masalah deklarasi @types/bluebird (tolong jangan habiskan waktu untuk membacanya). Saya menemukan, bahwa masalah dapat diselesaikan, dengan menambahkan export as namespace Promise; ke .d.ts, tetapi kemudian saya mengalami masalah yang dijelaskan oleh masalah github ini.

Singkatnya, saya ingin yang berikut ini berhasil:

  1. git clone -b vanilla-es5-umd-restriction-problem https://github.com/d-ph/typescript-bluebird-as-global-promise.git
  2. cd typescript-bluebird-as-global-promise
  3. npm install
  4. Edit node_modules/@types/bluebird/index.d.ts dengan menambahkan export as namespace Promise; atas baris export = Bluebird; .
  5. npm run tsc

Hasil saat ini:
Beberapa kesalahan 'Promise' refers to a UMD global, but the current file is a module. Consider adding an import instead. .

Hasil yang diharapkan:
Kompilasi berhasil.

Masalah ini sangat sulit, karena dipicu oleh penggunaan Promise di kedua kode dev dan kode pihak ketiga (RxJS dalam hal ini). Yang terakhir mengasumsikan bahwa Promise bersifat global (disediakan oleh standar JS), oleh karena itu tidak akan pernah berubah menggunakan misalnya import Promise from std; // (not that "std" is a thing) .

Saya sangat menghargai cara untuk menggunakan modul UMD baik sebagai modul yang dapat diimpor maupun sebagai modul global.

Terima kasih.

----------------------------- Pembaruan

Saya akhirnya menyelesaikan masalah ini secara berbeda (yaitu: dengan Promise dan PromiseConstructor antarmuka augmentasi).

Opsi "globals": [] tsconfig tampaknya lebih disukai daripada membuatnya terlihat di mana-mana. Dengan deklarasi UMD menjadi norma, kemungkinan lupa mengimpor modul secara tidak sengaja tinggi. Harap pertimbangkan untuk mempertahankan perilaku saat ini. Ini seharusnya kesalahan.

Secara anekdot saya ingat ketika saat menghapus variabel window.moment global mereka dalam rilis titik. Kami pikir kami telah mengimpornya dengan bijaksana di mana-mana, tetapi kami lupa tentang 5 tempat.

Tentu saja paket UMD akan tersedia dalam cakupan global saat runtime, tetapi ketersediaannya bergantung pada urutan pemuatan modul lain.

+1 ini. Saya baru saja mencoba menggunakan React dengan SystemJS, dan karena React tidak digabungkan dengan baik, saya hanya memuatnya langsung dari CDN dalam tag skrip, dan dengan demikian objek React / ReactDOM tersedia secara global.

Saya menulis kode sebagai modul sebagai praktik terbaik, tetapi ini akan digabungkan (Rollup) menjadi satu skrip runtime yang dijalankan saat dimuat. Sungguh menyakitkan (dan bohong) harus import from react / react-dom, lalu konfigurasikan loader untuk mengatakan "tidak juga, ini adalah global" (mirip dengan contoh konfigurasi WebPack yang diberikan di https: / /www.typescriptlang.org/docs/handbook/react-&-webpack.html). Akan jauh lebih mudah (dan lebih akurat) untuk menyediakan ini sebagai global dalam modul saya. Langkah-langkah yang saya coba, karena tampaknya intuitif, adalah:

  1. npm install --save-dev @types/react @types/react-dom
  2. Di tsconfig.json saya: "jsx": "react", "types": ["react", "react-dom"]
  3. Dalam modul saya: export function MyComponent() { return <div>{"Hello, world"}</div>; }
  4. Demikian pula: ReactDOM.render(...)

Namun ini menghasilkan kesalahan React refers to a UMD global, but the current file is a module. Consider adding an import instead .

Jika ini berhasil, ini akan jauh lebih sederhana daripada berpura-pura dalam kode itu adalah modul, lalu mengonfigurasi loader / bundler bahwa itu bukan. (Atau sebagai alternatif, saya agak mendapatkannya untuk melakukan apa yang saya harapkan dengan menambahkan file yang berisi di bawah ini. Sekarang modul saya dapat menggunakan React & ReactDOM sebagai global tanpa kesalahan, tetapi agak jelek / hacky - meskipun mungkin ada cara yang lebih sederhana saya ' sudah terlewat):

import * as ReactObj from "react";
import * as ReactDOMObj from "react-dom";

declare global {
    var React: typeof ReactObj;
    var ReactDOM: typeof ReactDOMObj;
}

Saya juga setuju dengan opsi tiga plus global: [] cadangan. Itu tampaknya cukup intuitif bagi pengguna baru dan lama dan akan memberikan fungsionalitas tepat yang dibutuhkan orang.

Saya bukan spesialis dalam kode jadi saya tidak bisa mengatakan apakah 2 akan lebih disukai atau tidak tetapi saya pikir itu juga akan intuitif mengingat konfigurasinya mudah.

Jika saya ingin mencari bantuan untuk menerapkan semua ini, ke mana saya harus pergi?

Ini benar-benar harus berada di belakang bendera. Ini adalah bahaya refactoring besar-besaran. Bahkan jika flag ditetapkan benar secara default. Saya pikir ini harus terus berfungsi dalam skenario asli jika tidak, kami kehilangan manfaat utama dari deklarasi UMD.

React tidak bisa digabungkan dengan baik

@billti dapatkah Anda menjelaskan?

Sungguh menyakitkan (dan bohong) harus import from react / react-dom, lalu konfigurasikan loader untuk mengatakan "tidak juga, ini adalah global"

Satu-satunya alasan saya menulis itu di tutorial adalah karena menggunakan externals menghemat waktu paket. Jika Anda menggunakan variabel global React tanpa mengimpor, Anda tidak dapat dengan mudah beralih ke modul nanti, sedangkan impor memberi Anda fleksibilitas untuk menggunakan salah satu dari loader yang diberikan.

Lihat masalah ini (https://github.com/rollup/rollup/issues/855) untuk satu contoh bagaimana mereka mencoba mengoptimalkan bundling dan ukuran yang diamati. Secara efektif dalam pengaturan saya (menggunakan Rollup), saya melihat keuntungan ukuran minimal membundel React, jadi saya lebih suka menyajikannya dari CDN. Bagi saya yang memiliki manfaat:

a) Lebih sedikit permintaan (dan bandwidth) ke situs saya.
b) Lebih sedikit waktu yang dibutuhkan untuk membundel dalam rantai build saya.
c) Lebih sedikit kode untuk diunduh ulang pada klien setiap kali saya mendorong perubahan (karena hanya kode saya yang ada dalam bundel yang diunduh ulang, dan Bereaksi masih dalam cache klien tanpa modifikasi - sehingga mendapatkan 304).

Melihat di Chrome Dev Tools saat memuat situs, React dan React-dom (versi yang diperkecil), pada koneksi HTTP GZipped, hanya 47kb dari lalu lintas jaringan, yang kurang dari kebanyakan gambar di situs, jadi saya tidak khawatir tentang mencoba mengurangi sebanyak itu, kecuali jika ada keuntungan yang benar-benar besar yang bisa didapat (misalnya pengurangan 50%).

Sebagai tambahan: Saya juga mencatat bahwa tanpa opsi ini, Anda juga memaksa orang untuk menggunakan bundler yang menghindari impor ini, karena compiler TypeScript sendiri tidak memiliki konfigurasi untuk mengatakan "modul ini benar-benar global", dan dengan demikian akan emit import (atau require, atau definisikan) untuk modul yang tidak dapat diselesaikan saat runtime.

@billti SystemJS memiliki dukungan penuh untuk skenario ini. Anda dapat bertukar antara menggunakan paket yang diinstal secara lokal selama pengembangan dan menggunakan CDN dalam produksi. Ini juga memiliki dukungan penuh untuk metadata yang menentukan bahwa semua impor harus benar-benar menunjukkan referensi ke variabel global yang akan diambil satu kali dan dilampirkan ke objek jendela saat pertama kali diperlukan, dalam produksi ini bisa berasal dari CDN. Saya belum melakukan ini dengan react tetapi saya telah melakukannya dengan sudut 1.x

Terima kasih @aluanhaddad . Menarik ... Saya sebenarnya mencoba untuk mendapatkan sesuatu yang serupa bekerja yang membawa saya ke penghalang jalan ini, dan tidak bisa mengetahuinya, jadi baru pagi ini mengajukan pertanyaan di repo SystemJS. Jika Anda dapat menjawab cara mencapai https://github.com/systemjs/systemjs/issues/1510, itu akan sangat membantu :-)

Catatan: Komentar saya yang lain masih berlaku, bahwa emit oleh TypeScript sendiri tidak dapat digunakan tanpa ini, karena Anda memerlukan sesuatu seperti SystemJS / WebPack / Rollup dll ... untuk memetakan impor ke global agar kode dapat dijalankan.

Saya akan melihat dan melihat apakah saya dapat membuat contoh yang berfungsi, saya belum melakukannya dalam waktu yang cukup lama dan saya tidak memiliki akses ke kode sumber yang saya miliki saat itu tetapi saya yakin seratus persen itu mungkin.

Untuk poin kedua Anda, itulah yang dilakukan SystemJS. Ini akan memetakan impor tersebut ke global dan memahami bahwa global sebenarnya sedang diminta dan telah dimuat. Outputnya pasti bisa digunakan

FYI: Saya mendapatkan ini berfungsi di SystemJS menggunakan SystemJS API dan menambahkan solusi saya di https://github.com/systemjs/systemjs/issues/1510 . Terima kasih.

Perihal poin kedua saya: Ya, saya tahu persis itulah yang dapat dilakukan loader. Itulah maksud saya, mereka dapat memetakan modul yang diimpor ke global, tetapi TypeScript tidak bisa - jadi Anda harus menggunakan loader untuk membuat kode Anda valid saat runtime. Jadi ini adalah tangkapan-22 dengan masalah asli ini, di mana Anda tidak dapat menyatakan bahwa global (dalam hal ini React) tersedia di modul, Anda harus mengimpornya seolah-olah itu adalah modul (yang sebenarnya bukan) .

Komentar saya yang lain masih berlaku, bahwa emit oleh TypeScript sendiri tidak dapat digunakan tanpa ini, karena Anda memerlukan sesuatu seperti SystemJS / WebPack / Rollup dll ... untuk memetakan impor ke global agar kode dapat dijalankan.

@billti Saya tidak mengerti. Apa skenario di mana satu-satunya pilihan Anda adalah menggunakan versi global modul, tetapi TypeScript tidak mengizinkan Anda untuk melakukannya? Aku hanya melihat skenario di mana perpustakaan tersedia baik sebagai global dan modul.

@DanielRosenwasser Saya rasa maksudnya React sebenarnya global pada saat runtime seperti dalam anggota objek global, karena cara pemuatannya.

@billti Mengagumkan bahwa Anda membuatnya berfungsi.

Re poin kedua Anda: Saya mengerti apa yang Anda maksud.

Saya rasa perasaan saya adalah, dalam skenario browser, karena Anda perlu menggunakan loader seperti RequireJS atau pengemas seperti Webpack karena tidak ada browser yang mendukung modul namun tidak ada bedanya. (Saya mendengar Chakra memilikinya tersedia di belakang bendera). Jadi tidak ada cara untuk menjalankan kode sama sekali tanpa alat tambahan. Ini adalah semacam implikasi dari keluaran yang berisi define , require , atau System.register bahwa kode _JavaScript_ yang dipancarkan tidak mungkin portabel. Namun, saya melihat pentingnya perbedaan "modul vs bukan modul".

Anda dapat menggunakan solusi ini untuk setidaknya hanya merujuk ke "modul" sekali.

_shims.d.ts_

import __React from 'react';

declare global {
  const React: typeof __React;
}

Kemudian Anda dapat menggunakannya di mana pun tanpa mengimpornya.
Ini juga sangat eksplisit, jika sedikit kludgy, karena Anda mengatakan bahwa React telah menjadi global dan itu juga alasan Anda tidak perlu mengimpornya lagi.

Re shims.d.ts Anda, jika Anda membuka beberapa posting, Anda akan melihat itulah yang saya lakukan untuk saat ini (pikiran yang hebat berpikir serupa) ;-)

Saya bisa membuatnya bekerja dengan salah satu dari beberapa cara sekarang, bukan itu intinya. Kami mencoba membuat TypeScript mudah diadopsi, dan membuat pengguna jatuh ke lubang kesuksesan, bukan lubang keputusasaan. Dengan pemikiran tersebut, saya sering bertanya pada diri sendiri dua pertanyaan ketika mencoba menggunakan TypeScript dan masalah yang dihadapi: a) Apakah ini kode yang valid, dan b) Apakah pelanggan akan mencoba dan melakukan ini.

Mengingat saya memiliki versi (non-TypeScript) melakukan apa yang saya inginkan di Babel kira-kira dalam waktu yang dibutuhkan saya untuk mengetiknya, saya pikir itu adil untuk mengatakan kode itu valid. Karena halaman instalasi dari dokumen React menunjukkan bagaimana menggunakan tag script dari CDN untuk memasukkan React, saya rasa sejumlah orang akan mencobanya juga. (FWIW: Saya telah menghabiskan lebih banyak waktu daripada yang saya inginkan untuk mengingat bekerja dengan berbagai modul dan pemuat JS, jadi bukannya saya tidak menyadarinya, saya hanya ingin menulis kode saya dengan cara ini).

Jika TypeScript tidak akan mendukung pola penulisan kode valid tertentu, kita harus mencoba membuatnya segera terlihat dan mengarahkan orang dengan benar (yang merupakan tantangan untuk dilakukan dalam pesan kesalahan atau dokumen ringkas). Tapi secara pribadi, menurut saya TypeScript seharusnya tidak mendukung pola karena menurut kami itu bukan "praktik terbaik" atau "kanonik". Jika kodenya valid, dan beberapa pengembang JavaScript mungkin ingin menulisnya, maka TypeScript harus mencoba mendukungnya. Semakin kita meminta mereka mengubah kode mereka dan mengkonfigurasi ulang pipeline build mereka agar TypeScript berfungsi (seperti yang disarankan di sini untuk memigrasi aplikasi sepele saya), semakin sedikit pengembang yang akan pindah.

Mengenai solusinya ... hanya spit-balling di sini, tetapi mungkin opsi compiler "lib", yang sudah secara efektif mendefinisikan API apa yang tersedia di seluruh proyek, juga dapat mengambil nilai format @types/name untuk ditambahkan perpustakaan secara global (dan bahkan mungkin mendukung jalur relatif).

Kami mencoba membuat TypeScript mudah diadopsi, dan membuat pengguna jatuh ke lubang kesuksesan, bukan lubang keputusasaan.

Saya pikir kami sedang mencoba mengarahkan pengguna ke lubang kesuksesan saat ini. Jika modul hanya mendefinisikan global secara bersyarat, maka Anda secara tidak sengaja membimbing pengguna untuk menggunakan sesuatu yang tidak ada. Jadi saya melihat beberapa opsi berbeda:

  1. Buat konstruksi export as namespace foo yang diperbesar yang hanya terlihat jika tidak diimpor oleh modul.
  2. Jangan lakukan apa-apa, dan terus dorong orang untuk menggunakan impor - ini kurang lebih baik menurut saya, karena kami telah membuat pesan kesalahan cukup preskriptif.
  3. Izinkan orang untuk menggunakan UMD dari mana saja - sejujurnya saya tidak terlalu paham tentang hal ini.

@tokopedia

Re shims.d.ts Anda, jika Anda membuka beberapa posting, Anda akan melihat itulah yang saya lakukan untuk saat ini (pikiran yang hebat berpikir serupa) ;-)

Maaf, saya melewatkan itu, sangat bagus;)

Menurut saya TypeScript seharusnya tidak mendukung pola karena menurut kami itu bukan "praktik terbaik" atau "kanonis"

Saya tidak berpikir TypeScript menjadi proscriptive di sini, saya pikir itu melakukan apa yang diklaimnya, memberi tahu saya bahwa saya mengalami kesalahan. Banyak perpustakaan memiliki demo dan tutorial di mana mereka memuat sendiri 'sebagai global dan kemudian melanjutkan untuk menggunakan sintaks Modul ES. Saya tidak berpikir mereka menjadi warga negara terhebat dengan melakukan ini, tetapi itu adalah diskusi lain.

Yang mengatakan, jika modul terutama digunakan sebagai gula sintaksis _perceived_ atas global, maka kegagalannya sudah dekat karena mereka sama sekali bukan gula sintaksis. Jika ada, mereka adalah garam sintaksis (mungkin pajak?) Yang kita konsumsi untuk manfaat seperti isolasi kode yang sebenarnya, kebebasan dari tag skrip ording, deklarasi ketergantungan eksplisit, melarikan diri dari neraka namespace global, dan manfaat lainnya. Sintaks untuk modul tidak ergonomis, paling banyak bertele-tele, tetapi semantik modullah yang membuatnya bermanfaat.

Saya pikir jika orang menggunakan TypeScript, setidaknya dalam .ts file, saya berasumsi mereka ingin mendapatkan manfaat dari analisis kode statis yang kuat. Babel tidak melakukan ini, dengan asumsi React ada tetapi tidak mengetahuinya. Ini benar meskipun Modul ES telah dengan sengaja ditentukan agar dapat menerima analisis statis.

@Bayu_joo

Buat ekspor tambahan sebagai konstruksi foo namespace yang hanya terlihat jika tidak diimpor oleh modul.

Kedengarannya seperti cara terbaik untuk menyelesaikan masalah ini.

Inilah kasus lain yang menyebabkan masalah:

Dalam proyek yang sedang saya kerjakan, kami menggabungkan penyertaan lokal (sebagian besar karena alasan historis) dengan modul npm. Pada akhirnya semuanya digabungkan menggunakan Rollup atau Browserify, jadi tidak apa-apa.

Saya menggunakan file .js dari proyek emojione yang baru saja saya salin ke dalam basis kode. Kemudian saya menambahkan deklarasi tipe untuk itu ke DefinitelyTyped: https://github.com/DefinitelyTyped/DefinitelyTyped/pull/13293 Saya pikir saya sekarang dapat memuat tipe dan semuanya akan bekerja. Tetapi tampaknya tidak demikian, karena TypeScript tidak mengizinkan saya mengakses global.

Alasan mengapa saya tidak pindah ke modul npm adalah karena modul npm juga menggabungkan beberapa megabyte sprite dan PNG. Saya hanya perlu satu skrip 200KiB itu. Dengan deklarasi tipe.

Dengan AngularJS, penyelesaiannya adalah declare var angular: ng.IAngularStatic . Tapi itu tidak berfungsi dengan namespace, bukan?

@dbrgn Anda mengalami masalah lain. Jika modul sebenarnya global, maka definisi tipe Anda salah. Ini tidak mendeklarasikan global, juga bukan deklarasi gaya UMD (ini tentang deklarasi gaya UMD), ini sebenarnya hanya mendeklarasikan Modul ES murni.

Jika modul mewakili global, jangan ekspor di tingkat atas file, itu membuatnya menjadi modul.

Dengan AngularJS, solusi tersebut dinyatakan var angular: ng.IAngularStatic. Tapi itu tidak berfungsi dengan namespace, bukan?

Ia bekerja dengan namespace.

Hasil diskusi pada pertemuan desain kami adalah bahwa kami mempertimbangkan untuk selalu mengizinkan UMD, dan menambahkan bendera yang memberlakukan pembatasan saat ini. Pembatasan juga akan diperluas untuk bekerja pada jenis akses dari UMD global.

Setelah memikirkan hal ini lebih lanjut, saya masih berpikir hal yang lebih baik untuk dilakukan adalah membuat jenis deklarasi baru. Bendera ini kurang dapat ditemukan dibandingkan sintaks baru, yang hanya perlu ditulis sekali oleh pembuat file deklarasi.

Ini sangat dibutuhkan untuk kode dan alat yang ada. Sampai Javascript berhenti bermain cepat dan kalah dengan sistem modul, kita membutuhkan fleksibilitas untuk bekerja dengan kode sebagaimana adanya. Berikan peringatan, tetapi jangan gagal dalam build. Saya telah membuang-buang hari untuk berurusan dengan membuat kode warisan bermain bagus dengan rollup dan skrip ketikan.

UGH.

Saya tahu ada banyak orang yang suka menertawakan Java, tetapi modul java dasar setidaknya berfungsi. Jars bekerja

Saya tidak harus menyesuaikan 14 standar modul ad hoc yang berbeda, atau mencoba dan mengompilasi modul js dari file sumber dalam format yang akan digunakan oleh alat rollup / bundling pada hari itu tanpa membuang kotoran itu sendiri, dan juga akan menghasilkan format modul yang akan bekerja dengan baik dengan pernyataan impor / ekspor Typecript dan file d.ts pihak ketiga sehingga TSC benar-benar akan memutuskan untuk membuat kode daripada mengeluh tentang sesuatu yang Anda tuju "HANYA GUNAKAN IMPOR DARN, ITU AKAN GLOBAL DI LARI WAKTU ".

Peretasan shims.d.ts bekerja dengan baik. Tapi ugh.

Solusi sementara bagi mereka yang menggunakan Webpack https://github.com/Microsoft/TypeScript/issues/11108#issuecomment -285356313

Tambahkan externals ke webpack.config.js dengan global UMD yang diinginkan.

    externals: {
        'angular': 'angular',
        'jquery': 'jquery'
        "react": "React",
        "react-dom": "ReactDOM"
    }

Saya rasa hal ini dapat dilakukan untuk mempermudah migrasi basis kode yang ada.

Saya memiliki proyek yang diimplementasikan dengan requirejs di mana jQuery disertakan sebagai global, karena ada beberapa plugin yang memperpanjang jQuery hanya jika ditemukan sebagai global.

Kode di beberapa modul bergantung pada plugin itu, yang tidak akan tersedia jika jQuery diimpor sebagai modul. Untuk membuat ini bekerja, saya harus memodifikasi semua plugin agar bekerja dengan jQuery yang dimuat sebagai modul, memuatnya juga sebagai modul (menebak di mana mereka diperlukan).

Selain itu, ada juga halaman yang menggunakan javascript tanpa module loader. Jadi, plugin harus berfungsi dengan global dan modul.

Selain jQuery, ada skrip lain dengan masalah yang sama seperti knockout dan lainnya. Hal ini membuat migrasi proyek menjadi mimpi buruk. Atau, dari sudut pandang realistis, tidak mungkin.

Tentu saja, ini bukan pola terbaik, dan saya tidak akan menggunakannya dalam proyek baru. Tetapi saya tidak berpikir saya satu-satunya dengan masalah ini

Apakah masuk akal menggunakan types dalam tsconfig.json untuk ini? Misalnya tanpa set types , Anda mendapatkan perilaku implisit saat ini dan dengan set types , Anda benar-benar mengatakan "hal-hal ini bersifat global" dan dapat memaksa namespace UMD muncul secara global. Begitulah perilaku yang ada saat ini (minus kekuatan global). Ini berlawanan dengan memperkenalkan opsi globals .

Saya pikir itu ide yang bagus. Dalam kasus saya ada script yang menggunakan perpustakaan UMD secara global, dan lainnya sebagai modul. Saya bisa menyelesaikan masalah ini dengan dua tsconfig.json berbeda yang menangani setiap kasus. Benar-benar lurus ke depan.

@blakeembrey Meskipun menggunakan types masuk akal, saya tidak terlalu tertarik pada gagasan overloading karena sudah memiliki masalah. Misalnya, konstruksi <reference types="package" /> sudah memiliki batasan yaitu tidak mendukung "paths" . "package" harus mengacu pada nama folder di @types

Saya mengalami kesulitan mengikuti percakapan ini. Apakah ada pembaruan atau resolusi yang direncanakan untuk ini? Sepertinya ini adalah sesuatu yang dapat berguna dalam skenario seperti ketika lodash merupakan bagian integral dari sebuah aplikasi, atau ketika lebih banyak perpustakaan pihak ke-3 mengonversi ke struktur yang lebih termodulasi daripada hanya mengandalkan berada di jendela.

Apakah ada cara terencana untuk mengatasi ini atau setidaknya untuk mendokumentasikan bagaimana ini harus diselesaikan dengan rilis yang tersedia saat ini?

Hai @mochawich Saya mendapatkan kesalahan berikut dengan menggunakan mendefinisikan React sebagai eksternal dan tidak menggunakan sintaks declare global :

TS2686: 'React' refers to a UMD global, but the current file is a module. Consider adding an import instead.

@cantux TypeScript tidak membaca konfigurasi Webpack. Jika Anda telah membuat React tersedia secara global, Anda dapat declare itu, tetapi mengapa tidak menggunakan modul?

@aluanhaddad kebanyakan karena saya bingung dengan pekerjaan yang dilakukan oleh panggilan impor. Saya mengotak-atik beberapa, apakah pernyataan berikut ini benar?

Kami membayar sedikit biaya untuk membuat permintaan saat kami mengimpor modul. Ini memastikan bahwa apa yang kita gunakan tersedia di memori, jika sebelumnya diminta, modul dimuat dari cache, jika modul tidak ada, itu diambil. Jika Anda ingin menghindari permintaan ini, Anda cukup mendefinisikan sesuatu sebagai global dan Typecript secara membabi buta mempercayai Anda bahwa itu tersedia (dan jika Anda menggunakan pernyataan impor smart bundler bahkan dapat diganti / dihapus).

Jika ini benar, kami dapat menghapus komentar agar singkatnya, utasnya sangat besar.

Seperti yang ditanyakan @codymullins di atas, dapatkah seseorang meringkas solusi saat ini untuk masalah ini? Saya baru saja memperbarui definisi tipe lodash dan mendapat banyak kesalahan TS2686.

Solusi saya saat ini adalah meretas file typedef agar sesuai dengan standar lama yang berfungsi tetapi itu tidak dapat dilakukan jika lebih banyak file typedef mulai rusak.

Skenario saya adalah sebagai berikut:

  • di aplikasi satu halaman saya, saya mengimpor sejumlah perpustakaan (termasuk lodash) di file

contoh shim yang disebutkan di atas berfungsi, meskipun vscode menyorotnya sebagai kesalahan (meskipun masih melakukan penyelesaian dengan benar!)

Mohon tolong jangan memberikan kesalahan saat mengakses UMD global di modul. Proyek besar yang sedang saya kerjakan dilakukan di AngularJS dan kami menggunakan Typecript untuk aplikasinya, tetapi tentu saja kami memerlukan Typecript untuk mengetahui tentang angular UMD global dan tipe Angular dari @types/angular . Anda akan berpikir itu semudah menambahkan "angular" ke types dalam tsconfig.json , tetapi, untuk alasan apa pun, tidak, dan TSC berteriak pada saya. Sebanyak saya berharap semua paket NPM adalah Typecript murni, kebanyakan dari mereka adalah JS biasa dan akan untuk waktu yang sangat lama. Saya benar-benar tidak mengerti mengapa TSC tidak bisa diam begitu saja ketika kita mengimpor d.ts mengatakan bahwa UMD global hadir. Situasi ini lebih dari umum - setiap proyek Typecript yang pernah saya kerjakan menggunakan setidaknya satu library JS yang harus saya gabungkan sendiri dan referensi menggunakan definisi tipe.

Apakah ada pembaruan tentang ini?

Kasus penggunaan saya: Saya sedang mengerjakan basis kode besar yang ada yang membuat banyak penggunaan CDN. Utilitas umum diimpor melalui tag skrip di banyak halaman (mis. Clipboardjs, lodash). Saya ingin merujuk variabel global tersebut karena tersedia di halaman. Tanpa menggunakan modul, cukup mudah untuk memiliki kompilasi skrip ketikan, menggunakan /// <reference type="$name" /> di bagian atas file sumber yang relevan. Namun ini berhenti bekerja saat mencoba membuat modul.

Tampaknya ada dua pendekatan yang diusulkan di utas:

  1. Minta token /// <reference type="$name" /> import hanya ke dalam namespace file saat ini.

  2. Variabel opsi / konfigurasi compiler di tsconfig.json (mis. "globals" , "types" )

Saya pikir kedua pendekatan itu bagus. Sementara saya setuju dengan kritik opsi 1 oleh @RyanCavanaugh :

Sebaliknya jika itu hanya tersedia dalam file itu, maka Anda harus menyalin dan menempel arahan referensi di semua tempat, yang sangat mengganggu.

Saya percaya jauh lebih menjengkelkan bahwa Anda tidak dapat menggunakan modul bersama dengan UMD global sama sekali karena perilaku saat ini. Beberapa solusi lebih baik daripada tidak sama sekali.

Apakah masalah ini masih beredar? Dan jika demikian, apa solusi saat ini?

Jika Anda menginstal paket @types , paket yang tidak diimpor sebagai modul, akan tersedia sebagai paket global.

Misalnya, jika saya npm install -D @types/underscore di root proyek saya, maka saya dapat menulis modul yang tidak mengimpor apa pun dari garis bawah, namun _ global telah tersedia (lihat di bawah).

types-ref

Itukah yang kamu cari?

@billti Mungkin saya salah paham, tetapi teladan Anda tidak berhasil untuk saya.

Minimal diperlukan untuk repro:

js / foo.ts:

// <reference types="js-cookie">

import { Bar } from "./bar";

const Foo = {
    set: function() {
        Cookies.set("foo", "bar");
    },
    get: function() {
        console.log(Cookies.get("foo"));
    }
};

window.onload = function() {
    console.log(Cookies);
}

js / bar.ts

const Bar = {
    x: 3
};

export { Bar };

package.json:

{
  "name": "foo",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "private": true,
  "devDependencies": {
    "@types/js-cookie": "^2.1.0",
    "typescript": "^2.7.1"
  },
  "dependencies": {
    "http-server": "^0.11.1"
  }
}

tsconfig.json

{
    "compilerOptions": {
        "module": "system"
    },
    "files": [
        "js/foo.ts"
    ]
}

Pesan kesalahan:

js / foo.ts (7,3): error TS2686: 'Cookies' mengacu pada UMD global, tetapi file saat ini adalah modul. Pertimbangkan untuk menambahkan impor sebagai gantinya.
js / foo.ts (10,15): kesalahan TS2686: 'Cookies' mengacu pada UMD global, tetapi file saat ini adalah modul. Pertimbangkan untuk menambahkan impor sebagai gantinya.
js / foo.ts (15,14): kesalahan TS2686: 'Cookies' mengacu pada UMD global, tetapi file saat ini adalah modul. Pertimbangkan untuk menambahkan impor sebagai gantinya.

Perilaku yang Anda dapatkan bergantung pada apakah modul yang diimpor ditulis sebagai modul UMD yang "tepat" (ini adalah perilaku dengan "Cookies") atau modul "bekerja dua arah pada saat yang sama" (begitulah cara penulisan lodash) .

Ketidakkonsistenan orang yang menulis file .d.ts dengan benar yang menjelaskan cara kerja objek saat runtime, dan ketidakjelasan pengalaman untuk pengembang, adalah alasan mengapa saya bersandar cukup keras ke arah "hapus pembatasan global UMD". Kita bisa meletakkannya di bawah --strict dengan --noStrictUMD opt-out.

Hal lain yang saya hadapi adalah berurusan dengan pemuat AMD kustom Monaco. Mereka mendukung beberapa subset dari perilaku AMD (memasukkan eyeroll yang sangat besar) tetapi menginjak global 'membutuhkan' sehingga sangat sulit untuk menggunakan modul UMD yang tepat dengannya karena modul tersebut cenderung melihat 'membutuhkan' global dan kemudian gagal memuat dengan benar ke dalam Pemuat modul Monaco. Anda akhirnya meletakkan UMD JS libs di atas tag skrip untuk Monaco loader dan kemudian TS mengeluh karena Anda mengakses global dari modul (yang Anda harus mengimpor API Monaco).

@RyanBarokah

Hal lain yang saya hadapi adalah berurusan dengan pemuat AMD kustom Monaco. Mereka mendukung beberapa subset dari perilaku AMD (memasukkan eyeroll yang sangat besar) tetapi menginjak global 'membutuhkan' sehingga sangat sulit untuk menggunakan modul UMD yang tepat dengannya karena modul tersebut cenderung melihat 'membutuhkan' global dan kemudian gagal memuat dengan benar ke dalam Pemuat modul Monaco.

😁

Ada kemungkinan mereka memperbaikinya?

Saya telah banyak memikirkan tentang biaya kompleksitas modul akhir-akhir ini. Begitu banyak pemuat, pemaket, transpiler, pengelola paket, dan kerangka kerja yang saling bergantung, sebagian kompatibel dengan jumlah kompleksitas akreditasi yang benar-benar tidak remeh. (Saya yakin Anda tidak perlu diingatkan sama sekali 🙉).

Sebagai pengembang, kami telah menerima rantai alat yang lipat lebih kompleks daripada yang kami miliki 5-6 tahun yang lalu, dan sumber utama kerumitan adalah modul.

Jika kita menyerah dan mulai memuat paket UMD ini sebagai global, untuk apa semuanya?

Namun ... orang-orang melakukan itu. Ini mengerikan!

Maksud saya, Jawaban Stack Overflow ini memiliki 61 dan telah menyarankan semua hal yang salah untuk 99% paket selama setengah tahun terakhir. (penulis dengan hormat memperbaruinya untuk menyebutkan modul sebagai _option_ untuk dependensi UMD karena beberapa umpan balik yang diberikan pagi ini)

Ini tidak bisa membiarkan semua ini terjadi dan kembali ke global!

Namun ... orang-orang melakukan itu. Ini mengerikan!

Masalahnya adalah bahwa modul JS sangat buruk dipahami dan diterapkan, jadi jauh lebih baik dan lebih mudah untuk kembali menggunakan global. Jika modul telah dirancang dan diimplementasikan dengan benar sejak awal ...

Kami mencampur-dan-mencocokkan modul dan UMD global karena terlalu merepotkan untuk memuat dependensi kami sebagai modul dengan berbagai tingkat kompatibilitas dengan berbagai pemuat dan beberapa pemuat tidak mendukung bundling ketergantungan langsung dan sebaliknya Anda harus menggunakan preprocessor khusus kami yang membutuhkan menit untuk berlari.

"Fitur" ini hanya berarti kami tidak menggunakan dukungan modul UMD resmi padahal sebenarnya kami menggunakan modul UMD. Kami hanya mengekspor sebagai global dari file .d.ts dan kemudian secara manual memiliki modul kami sendiri dengan nama itu yang mengekspor ulang semuanya.

Ada pembaruan tentang ini? Saya sangat ingin opsi 2 berfungsi:

Izinkan beberapa sintaks atau konfigurasi untuk mengatakan "UMD global ini sebenarnya tersedia secara global"

Juga tidak membantu bahwa ada begitu banyak js libs gaya jadul
di sana, dan menulis ulang semuanya tidak mungkin. Hanya berolahraga dengan solid
config untuk mendapatkan Rollup untuk menangani mereka semua dengan benar membuang-buang waktu saya berjam-jam.

Orang-orang menertawakan "Enterprise Java", tetapi Java biasa dikirim dengan aplikasi yang bisa diterapkan
sistem modul di 1.0. Tidak sempurna, tapi tidak berantakan.

Karena "Izinkan gaya global UMD" pasti menjadi pilihan.

Pada hari Sen, 2 Apr 2018 jam 01.40 Kagami Sascha Rosylight <
[email protected]> menulis:

Saya harus mengatasinya dengan:

/ * modul: es2015 * /
// js-yaml mendukung UMD tetapi tidak mendukung modul ES2015! import * as _jsyaml dari "js-yaml"; deklarasikan var jsyaml: typeof _jsyaml; jsyaml.safeLoad ("");

-
Anda menerima ini karena Anda berkomentar.
Balas email ini secara langsung, lihat di GitHub
https://github.com/Microsoft/TypeScript/issues/10178#issuecomment-377885832 ,
atau nonaktifkan utasnya
https://github.com/notifications/unsubscribe-auth/AA50ljAD33sr09EGFVAsURbu1x75X-lOks5tkeQCgaJpZM4Jd8jX
.

>

Daniel Joyce

Orang yang lemah lembut akan memiliki bumi, karena yang berani akan berada di antara bintang-bintang.

Saya menggunakan three.js dalam proyek Angular. Saya mengimpornya sebagai

import * as THREE from "three";

import {Vector3} from "three"; juga berfungsi seperti yang diharapkan.

Dengan paket three dan @types/three npm terinstal, semuanya bekerja dengan baik. Di bawah tenda, saya kira ini menggunakan three/build/three.module.js . File @types/three/index.d.ts menggunakan notasi export as namespace THREE , yang saya tidak terlalu nyaman dengannya, tapi hei berhasil.

Dalam kasus khusus ini, masalahnya adalah ada file terkait lainnya di sistem three.js yang disebut OrbitControls.js (yang memungkinkan Anda memutar gambar 3d dengan jari atau mouse Anda, pada dasarnya). Masalahnya adalah meskipun fungsi ini semi-resmi bagian dari distribusi three.js, ini adalah file JS biasa yang ditemukan di pohon examples dan secara langsung menempatkan dirinya pada properti THREE jendela, dan langsung menggunakan API lain yang diharapkan akan ditemukan di window.THREE . Jadi, meskipun saya "memerlukan" file dengan

require("three/examples/js/controls/OrbitControls.js");

ia tidak dapat menemukan window.THREE untuk menempatkan dirinya, atau untuk mengakses bagian lain dari sistem TIGA yang digunakannya. Saya dapat menyertakan seluruh perpustakaan secara langsung menggunakan properti Angular scripts di angular.json (kira-kira setara dengan tag <script> kuno), tetapi kemudian jika saya tidak salah saya akan memuat perpustakaan dua kali.

Untuk menghindarinya, saya menghapus pernyataan import * as THREE from "three"; , dan hei, itu masih bisa menyelesaikan jenis seperti foo: THREE.Vector3 , tetapi tersedak referensi seperti new THREE.Vector3() dengan yang terkenal

'TIGA' mengacu pada UMD global, tetapi file saat ini adalah modul. Pertimbangkan untuk menambahkan impor sebagai gantinya. [2686]

Pada titik ini saya berpikir saya hanya harus mengambil file OrbitControls.js dan ES6-ify dan / atau TS-ify itu, yang tampaknya sudah dilakukan oleh lebih dari satu orang lain di bentuk hal-hal seperti `orbit-kontrol-es6 , jadi mungkin saya harus menyederhanakan hidup saya dan menggunakannya, meskipun saya benci meletakkan hidup saya di tangan orang lain seperti itu.

Pada catatan semi-tidak berhubungan, satu keanehan adalah bahwa @types/three mendefinisikan tipe untuk OrbitControls , bahkan melalui kode itu sendiri tidak ada dalam modul three itu sendiri. Namun, saya tidak tahu bagaimana mengasosiasikan semua tipe yang mendefinisikan kelas yang disebut OrbitControls dengan apapun - Saya ingin menyatakan ekspor default dari orbit-controls-es6 disebutkan di atas menjadi dari tipe ini, tapi bagaimana melakukannya membuatku tidak mengerti.

Solusi yang akhirnya saya dapatkan, yang membuat saya sangat malu, adalah:

import * as THREE from "three";
Object.defineProperty(window, "THREE", {get() { return THREE; }});
require("three/examples/js/controls/OrbitControls.js");

Itu berhasil, meskipun saya sedikit bingung mengapa. File yang dibutuhkan memiliki baris seperti

THREE.OrbitControls = funtion() { };

yang tampaknya akan berakhir dengan menetapkan ke TIGA "namespace" yang dihasilkan dari pernyataan import * as THREE from "three"; , yang seharusnya tidak berfungsi, bukan?

@RyanCavanaugh meminta saya untuk menyalin umpan balik saya dari # 26223 di sini:

Saya mempertahankan basis kode TypeScript yang agak besar (monorepo internal Google) yang memiliki beberapa pustaka yang pasti diketik yang bergantung pada orang. Awalnya pengguna hanya akan mengandalkan tipe global untuk pustaka seperti angular , sebelum .d.ts diubah menjadi modul eksternal. Kami kemudian memigrasi basis kode untuk menggunakan modul dan impor eksplisit. Kami benar-benar berharap bahwa export as namespace d global UMD akan selalu memerlukan impor eksplisit untuk menggunakan simbol, untuk referensi tipe dan nilai, dan bahkan tidak menyadarinya ketika kami bermigrasi (ups).

Mengizinkan penggunaan kode yang tidak diimpor umumnya bermasalah bagi kami:

  • itu berarti kode bergantung pada definisi tipe "latar belakang" global, membuat kode lebih sulit dibaca (khususnya di browser repo atau tinjauan kode tanpa menggunakan simbol).

  • itu mengaburkan dependensi kode

  • itu mengelak dari batasan "harus memiliki ketergantungan tingkat pembangunan eksplisit pada semua impor" yang kami terapkan di bazel, alias "deps ketat".

    Dalam basis kode yang besar, kode Anda harus memiliki dependensi eksplisit, jika tidak, repo menjadi tidak dapat dikelola. Sekarang jika Anda memiliki ketergantungan chaing A -> B -> C dan tipe global, mudah untuk memiliki kode A kompilasi hanya karena B memiliki ketergantungan pada C . Jika B kemudian menghapus ketergantungannya, itu merusak A , yang berarti perubahan memiliki efek riak yang tidak terduga pada repositori, melanggar isolasi kode.

  • itu menyebabkan kode mengimpor modul secara tidak konsisten dengan satu awalan untuk nilai dan menggunakan tipenya dengan awalan lain (khususnya untuk AngularJS, ng vs angular)

Kami dapat mengatasinya dengan menghapus pernyataan export as namespace di salinan DefinitelyTyped milik vendor, tetapi setidaknya bagi kami, fitur ini berfungsi melawan pemeliharaan kode dan tujuan teknik kami. Saya pikir masalahnya lebih parah dalam situasi monorepo seperti Google, tetapi umumnya juga berlaku dalam basis kode yang lebih kecil.

Poin-poin yang Anda posting sama sekali tidak penting bagi situasi kami. Kami dipaksa untuk mengimplementasikan kode kami sendiri dengan modul AMD dan memasok dependensi kami dengan modul UMD karena keadaan yang secara luas di luar kendali kami (tapi saya akan meringkas sebagai modul JS yang sangat cacat dalam konsep dan implementasi). Fitur ini akan memungkinkan kita untuk sangat menyederhanakan hidup kita.

Mungkin dengan TS3 kami dapat menemukan cara untuk menghindari hal ini, tetapi bahkan jika kami melakukannya, mungkin akan membutuhkan setidaknya dua tahun sebelum kami menyelesaikan semua perubahan yang diperlukan, jadi ini masih akan menjadi fitur yang sangat berguna bagi kami.

Pertanyaan terbuka: Apakah satu tanda global untuk "Izinkan akses ke semua modul UMD" sudah cukup, atau apakah orang benar-benar memerlukan kontrol per modul atas kesalahan tersebut?

Beri suara ❤️ untuk "hanya satu bendera"
Beri suara 🎉 untuk "kebutuhan kontrol per modul"

Saya juga mempertimbangkan jika kehadiran daftar eksplisit dalam opsi "types" di tsconfig.json seharusnya juga tidak mengizinkan penggunaan UMD dalam modul. Itu menandakan tipe itu hadir dengan sengaja. (Meskipun jelas tidak menghalangi kesalahan karena Anda lupa mengimpornya).

Atau serupa, menggunakan konstruksi /// <reference types="..." /> harus mengizinkan penggunaan UMD dari paket itu dalam modul yang digunakannya (yaitu 'kontrol per modul' disebutkan).

@RyanCavanaugh Apakah akan ada bendera ke alamat # 26233 juga?

26233 dianggap berfungsi penuh sebagaimana dimaksud; mengakses sisi tipe UMD global dari modul secara sah tidak berbahaya

Saya tidak begitu yakin apakah itu "secara sah tidak berbahaya". Menggunakan @types/jquery sebagai contoh. $ dan jQuery dipetakan ke antarmuka JQueryStatic dan diekspor sebagai konstanta. Hasilnya, semua modul dapat mengakses $ dan jQuery tanpa impor. Saya harap saya bisa menonaktifkannya.

@RyanCavanaugh ya, itu tidak berbahaya dalam arti TS yang dipancarkan tidak terpengaruh olehnya. Ini bermasalah jika Anda ingin kontrol yang sangat baik atas apa yang @types dapat diakses setiap perpustakaan - itu mengubah apa yang setidaknya terlihat seperti tipe cakupan modul menjadi tipe global. Memperluas akses juga bisa menjadi masalah, bahkan jika emit tidak terpengaruh.

Sebenarnya dalam kasus jQuery, emit terpengaruh. $() dipancarkan dalam modul tanpa impor.

Menerima PR untuk bendera baru yang memungkinkan akses ke UMD global dari semua modul.

Dari segi penerapan, ini cukup mudah ... tetapi kita perlu menamainya. Kami menendang sekitar selusin nama buruk pada pertemuan tinjauan saran dan membenci semuanya, jadi terserah Anda untuk menemukan sesuatu yang enak. Tolong berhenti.

Kami menendang sekitar selusin nama buruk pada pertemuan tinjauan saran dan membenci semuanya

Apa itu?

jadi terserah kalian untuk menemukan sesuatu yang enak.

Mungkin umdUseGlobal atau sesuatu.

Saya akan menyarankan importAllNamespaces untuk nama bendera global UMD karena UMD global biasanya export as namespace .

@RyanCavanaugh Apakah tim berdiskusi tentang masalah tipe?

@Ranky_rizal iya.

@saschanaz Sudah menanyakan hal ini, tetapi saya juga penasaran ... @RyanCavanaugh Apakah Anda ingat nama-nama buruk apa yang dibahas?

Saya pikir rantai itu berjalan seperti ini

  • allowUmdGlobalAccessFromModules - paling tepat tapi sangaaaat panjang
  • assumeGlobalUmd - ugh
  • allowModuleUmdGlobals - "global" ??
  • umdAlwaysGlobal - 🤢
  • allowUmdGlobals - tapi saya sudah bisa?
  • allowUmdGlobalAccess - melewatkan bagian modul tapi mungkin tidak ada yang peduli?

Saya akan memilih yang terakhir jika terpaksa

Terima kasih!

Saya paling suka allowUmdGlobalAccessFromModules karena, meskipun panjang, ketepatannya membuatnya paling mudah diingat. Saya akan berpikir, "Opsi apa yang memungkinkan UMD global untuk diakses dari modul? Oh ya, tentu saja allowUmdGlobalAccessFromModules !"

Menggunakan awalan "allow" cocok dengan konvensi penamaan opsi lain, dan itu bagus.

Plus ... ada opsi lain yang kira-kira sepanjang :)

allowUmdGlobalAccessFromModules : 31 karakter

allowSyntheticDefaultImports : 28 karakter
strictPropertyInitialization : 28 karakter
suppressExcessPropertyErrors : 28 karakter
suppressImplicitAnyIndexErrors : 30 karakter
forceConsistentCasingInFileNames : 32 karakter

Apa solusi saat ini? Saya telah googling selama satu jam terakhir dan tidak dapat menemukan solusi yang bisa diterapkan.
Saya lebih suka tidak melakukan cast ke 'any' atau downgrade ke versi Typecript yang berfungsi tetapi tidak dapat menemukan opsi lain.
Apakah ada build eksperimental di suatu tempat yang memiliki flag compiler yang memperbaiki masalah ini?
(ngomong-ngomong, 'allowUmdGlobalAccessFromModules' adalah nama yang bagus; bukan berarti kita mengetiknya 50 kali sehari :-))

Kami menggunakan tsc 3.2.2 dengan lodash yang secara statis disertakan di file HTML teratas; dengan require.js; d. diperoleh dari DefinitelyTyped terbaru; contoh kode yang gagal untuk dikompilasi:

/// <reference path="..." />

class Example<T extends IThingWithTitle<T>> {

    public test = (arg : T[]) : void => {
        _.sortBy(arg, (el : T) => { return el.title; }); // TS2686: '_' refers to a UMD global, but the current file is a module. Consider adding an import instead.
    };

}

export = Example;

(tolong jangan beri tahu saya bahwa saya perlu membalikkan proyek, saya tahu kita berada di belakang kurva dalam beberapa aspek)

Pembaruan: ((window) ._) / * FIXME https://github.com/Microsoft/TypeScript/issues/10178 * /. sortBy (...) berfungsi tapi ya Tuhan, itu jelek :-P

@Gilead , solusi dari komentar ini berfungsi dengan baik untuk saat ini: https://github.com/Microsoft/TypeScript/issues/10178#issuecomment -263030856

Apakah ada kemajuan dalam hal ini? Saya memiliki kasus di mana penyelesaian yang disebutkan tampaknya tidak berfungsi (menggunakan [email protected] ) karena saya mengalami masalah ini.


Pertama saya mencoba ini:

import 'firebase';

declare global {
  const firebase;
}

Ini secara implisit memberikan firebase global tipe any , dan kemudian menerapkan namespace (dengan nama yang sama) padanya. Pertama, ini sepertinya berhasil karena ini menunjukkan tooltips / intellisense yang tepat untuk semua kunci tingkat atas firebase .

Namun itu tidak benar-benar berfungsi (saya berasumsi karena kemudian beralih menggunakannya sebagai tipe any , yang mungkin merupakan bug?):


Jadi saya mencoba solusi yang disebutkan di sini tetapi tidak berhasil (meskipun berhasil untuk orang lain):

import _firebase from 'firebase'; // same with = require('firebase') 

declare global {
  const firebase: typeof _firebase;
}

=> 'firebase' direferensikan secara langsung atau tidak langsung dalam anotasi tipenya sendiri.
(meskipun namespace adalah alias?)


Saya juga mencoba

import * as _firebase from 'firebase';

declare global {
  const firebase: typeof _firebase;
}

=> Definisi melingkar dari alias impor '_firebase'.
(mungkin karena definisi export = firebase; export as namespace firebase; ?)


Dan akhirnya, jika saya melakukan import 'firebase' , saya kembali

'firebase' mengacu pada UMD global, tetapi file saat ini adalah modul. [2686]


Jika ada yang punya solusi untuk ini, itu akan sangat dihargai. Jika tidak, salah satu saran untuk menyelesaikan ini yang disebutkan sejauh ini tampaknya baik-baik saja bagi saya (bendera, referensi garis miring tiga, types di tsconfig, memiliki objek global atau external di tsconfig).

Komentar Re

Ini tidak bisa membiarkan semua ini terjadi dan kembali ke global!

Saya tidak mencoba untuk kembali ke global, saya hanya mencoba agar beberapa dependensi berat dimuat secara terpisah dari app bundle saya, sambil tetap menggunakan modul untuk yang lainnya, karena ini membawa beberapa manfaat: dependensi dapat di-cache dengan benar karena mereka tidak diperbarui sesering app bundle saya; ukuran paket saya tidak meledak (terkadang karena pemecahan kode, bundler menyertakan ketergantungan yang sama beberapa kali), yang berarti lebih sedikit mengunduh untuk pengguna aplikasi saya; membangun kembali bundel saya selama dev jauh lebih cepat.

Ini benar-benar fitur yang sangat mudah untuk ditambahkan; akan sangat bagus bagi anggota komunitas untuk mengambilnya.

@RyanCavanaugh Saya compiler/types.ts dan memodifikasi cek global umd di compiler/checker.ts , dan saya rasa saya perlu menambahkannya ke compiler/commandLineParser.ts juga ... tapi saya pikir akan memakan waktu cukup lama untuk menyelesaikannya karena saya sama sekali tidak terbiasa dengan sumbernya (seperti bagaimana cara menambahkan deskripsi untuk bendera CLI tanpa merusak i18n) . Untuk saat ini saya akan menunggu orang lain yang mengetahui sumbernya untuk mengambil alih.

@simonhaenisch Anda dapat mendeklarasikannya dalam file deklarasi non-modul, dan untuk menghindari referensi melingkar, Anda dapat mengekspornya kembali dalam deklarasi modul UMD lainnya. firebase dideklarasikan sebagai namespace, beruntung bagi kami, ini akan menambah deklarasi kami, tidak menyebabkan kesalahan.

// umd.d.ts
import firebase = require("firebase");
export import firebase = firebase;
export as namespace UMD;

// global.d.ts
declare const firebase: typeof UMD.firebase;

Sayangnya, yang kami nyatakan adalah nilai, bukan namespace, jadi Anda tidak dapat melakukan sesuatu seperti let x: firebase.SomeInterface , satu-satunya cara untuk membuat alias namespace adalah dengan mendeklarasikan impor, tetapi Anda tidak bisa declare import firebase = UMD.firebase; , karena namespace tidak akan menambahnya. Tentu kita dapat menggunakan nama yang berbeda hanya untuk namspace yang menggunakan tipe, tetapi itu akan menyebabkan kebingungan, saya lebih suka membuang sisa kode yang saya bicarakan di atas, menetapkannya ke nilai global saat runtime, membuat alias impor benar-benar berfungsi.

Mirip dengan komentar sebelumnya, kami lazy-loading hls.js (UMD) dan tipe referensi sebagai berikut:

Di hls.d.ts :

import * as Hls from 'hls.js';
declare global {
    const Hls: typeof Hls;
}

Dalam file .ts menggunakan modul UMD yang dimuat lambat:

/// <reference path="hls.d.ts" />
// now use it
if(Hls.isSupported()){
 ...
} 

Diuji dalam Ketikan> = 3.0.1 dan 3.4.1.

Alasannya adalah dukungan browser tidak lengkap untuk impor modul dinamis.

@MatthiasHild Bisakah itu dilakukan tanpa komentar /// <reference path="hls.d.ts" /> ?

EDIT, ya bisa, selama deklarasi itu ada dalam file .d.ts yang TIDAK memiliki nama yang sama dengan file .ts , berdasarkan pertanyaan SO ini (itulah yang membuat saya dan mengapa saya bertanya).

Apakah halaman ini membantu?
0 / 5 - 0 peringkat

Masalah terkait

Gaelan picture Gaelan  ·  231Komentar

nitzantomer picture nitzantomer  ·  135Komentar

rbuckton picture rbuckton  ·  139Komentar

rwyborn picture rwyborn  ·  210Komentar

fdecampredon picture fdecampredon  ·  358Komentar