Typescript: Berikan cara untuk menambahkan ekstensi file '.js' ke akhir penentu modul

Dibuat pada 16 Jun 2017  ·  273Komentar  ·  Sumber: microsoft/TypeScript

Untuk menggunakan modul es6 di browser, Anda memerlukan ekstensi file .js. Namun output tidak menambahkannya.

di ts:
import { ModalBackground } from './ModalBackground';
Dalam keluaran ES2015:
import { ModalBackground } from './ModalBackground';

Idealnya saya ingin ini menjadi output
import { ModalBackground } from './ModalBackground.js';

Dengan begitu saya bisa menggunakan output di Chrome 51

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Webpack boilerplate</title>
  <script type="module" src="index.js"></script>
</head>
<body></body>
</html>

image

Terkait dengan https://github.com/Microsoft/TypeScript/issues/13422

ES Modules Needs Proposal Suggestion

Komentar yang paling membantu

Juga, untuk sedikit menggeneralisasi masalah ini, saya tidak berpikir ini sebenarnya tentang menambahkan ekstensi .js , tetapi menyelesaikan penentu modul ke jalur yang sebenarnya, apa pun ekstensinya.

Semua 273 komentar

Ini tidak hanya terkait dengan #13422, ini adalah masalah yang sama. Tetapi tanggapannya cukup negatif, meskipun saya pikir itu masalah penting, jadi harap masalah Anda akan diterima dengan lebih baik.

Yah, saya harap ini ditambahkan, kami sangat menantikan untuk mendiskusikan POC saya menggunakan ini di podcast TypeScript saya berikutnya, tetapi sepertinya kami harus menunggu untuk menggunakan TypeScript tanpa alat build.

Saat ini TypeScript tidak menulis ulang jalur. Ini benar-benar menjengkelkan, tetapi saat ini Anda dapat menambahkan ekstensi .js sendiri.

@justinfagnani @rictic

Terima kasih atas tipnya, saya akan menulis skrip Shell/node untuk melakukan ini.

@DanielRosenwasser apakah masuk akal untuk mengumpulkan masalah modul ES6 asli di bawah label?

Juga, untuk sedikit menggeneralisasi masalah ini, saya tidak berpikir ini sebenarnya tentang menambahkan ekstensi .js , tetapi menyelesaikan penentu modul ke jalur yang sebenarnya, apa pun ekstensinya.

Saya telah menemukan masalah lain yang sebenarnya bukan domain dari TypeScript tetapi untuk kasus penggunaan saya.

Saya tidak yakin bagaimana menangani node_modules. Biasanya webpack menggabungkannya ke dalam kode melalui ts-loader tetapi jelas, ini tidak dipahami oleh browser:

import { KeyCodes } from 'vanilla-typescript;
https://github.com/quantumjs/vanilla-typescript/blob/master/events/KeyCodes.ts#L3

Menambahkan ekstensi js di sini tidak ada artinya.

Saya kira harus ada perluasan jalur dengan TypeScript atau resolver url yang berjalan di server.

Saya menghargai ini kasus yang agak khusus, tapi saya pikir itu akan menjadi cara TS bisa bersinar lebih awal di area ini. Mungkin itu bisa menjadi plugin untuk kompiler tsc?

Bagi siapa pun yang datang ke ini dan menginginkan solusi sementara, saya menulis skrip untuk menambahkan ekstensi file js untuk mengimpor pernyataan:

"use strict";

const FileHound = require('filehound');
const fs = require('fs');
const path = require('path');

const files = FileHound.create()
  .paths(__dirname + '/browserLoading')
  .discard('node_modules')
  .ext('js')
  .find();


files.then((filePaths) => {

  filePaths.forEach((filepath) => {
    fs.readFile(filepath, 'utf8', (err, data) => {


      if (!data.match(/import .* from/g)) {
        return
      }
      let newData = data.replace(/(import .* from\s+['"])(.*)(?=['"])/g, '$1$2.js')
      if (err) throw err;

      console.log(`writing to ${filepath}`)
      fs.writeFile(filepath, newData, function (err) {
        if (err) {
          throw err;
        }
        console.log('complete');
      });
    })

  })
});

Saya mungkin membuat ini menjadi alat cli ..

Komentar @justinfagnani menyentuh kepala.

Juga, untuk sedikit menggeneralisasi masalah ini, saya tidak berpikir ini sebenarnya tentang menambahkan ekstensi .js, tetapi menyelesaikan penentu modul ke jalur yang sebenarnya, apa pun ekstensinya.

saat kamu menulis

import { KeyCodes } from 'vanilla-typescript';

atau dalam hal ini

import { KeyCodes } from 'vanilla-javascript';

Anda mengimpor dari specifier modul, itu mungkin atau mungkin bukan file tetapi menambahkan .js ke akhir dalam hal ini kemungkinan tidak akan menghasilkan resolusi yang valid.

Jika Anda menulis aplikasi NodeJS maka algoritma NodeJS Require akan mencoba berbagai resolusi tetapi kemungkinan akan _not_ mencoba untuk menyelesaikannya menjadi 'vanilla-typescript.js' karena merujuk pada nama abstrak dan akan, dengan konvensi dan konfigurasi, diselesaikan ( mungkin melalui berbagai upaya) untuk sesuatu seperti '../../../node_modules/vanilla_typescript/index.js' .

Lingkungan lain, seperti AMD memiliki perbedaan tentang cara mereka melakukan resolusi ini, tetapi satu hal yang dimiliki semua lingkungan ini adalah beberapa gagasan tentang penentu modul yang diabstraksikan.

Saya mengemukakan ini karena implementasi Modul ES yang dikirim di berbagai browser mengimplementasikan sesuatu yang tidak lengkap. Jika kita mempertimbangkan bahkan ketergantungan kita yang paling sederhana, dan segera setelah kita membahas subjek transitif, menjadi jelas bahwa perlu ada cara untuk mengkonfigurasi hal doggone.

Itu mungkin jauh, tetapi seperti yang Anda temukan, tidak realistis untuk menulis bukti implementasi konsep (dengan sopan) yang telah kami berikan ini.

Selain itu, saya tidak melihat bagaimana TypeScript dapat membantu di sini karena masalahnya khusus untuk lingkungan.

@QuantumInformation program Anda untuk menambahkan .js ke jalur terlihat bagus, ringan, bahkan elegan, tetapi Anda akhirnya mengimplementasikan bundler modul Anda sendiri. Itu adalah pekerjaan yang menyenangkan dan menarik tetapi ini menunjukkan kekurangan dalam implementasi saat ini yang tersedia di browser. Bahkan jika Anda menulis dalam JavaScript murni, Anda masih memerlukan sesuatu untuk mengompilasi dan mengemas dependensi yang diimpor secara transitif.

Saya pada dasarnya hanya mengomel tentang fakta bahwa implementasi Modul ES yang dirilis sangat jauh dari memadai.

Sekali lagi NodeJS, RequireJS AMD, Dojo AMD, Sea Package Manager, CommonJS, Browserify, Webpack, SystemJS, semuanya memiliki cara berbeda dalam melakukan sesuatu tetapi semuanya memberikan resolusi nama abstrak. Mereka harus menyediakannya karena itu _fundamental_.

Terima kasih telah membaca curhatan saya.

Tidak yakin versi TS mana yang menambahkannya, tetapi impor seperti ' ./file.js' sekarang berfungsi (bahkan jika file sebenarnya adalah file.ts).
TypeScript menyelesaikan file dengan baik, dan mengeluarkan impor .js lengkap ke target.
lit-html gunakan: https://github.com/PolymerLabs/lit-html/blob/master/src/lib/repeat.ts#L15

Itu mungkin sejak TS 2.0. Tetapi alat seperti webpack tidak mendukungnya sehingga pada akhirnya tidak ada gunanya.

Tidak ada gunanya jika seseorang menggunakan ts-loader pada sumber (kasus penggunaan yang paling umum).
Masih mungkin untuk menggabungkan target (biasanya folder "dist"), karena file js yang sebenarnya ada di sana dan dapat ditemukan oleh proses resolusi.

Saya ingin tahu apakah saya dapat menerapkan transformasi cepat dalam ts-loader yang menghapus ekstensi .js dari kode target, memungkinkan seseorang untuk membundel langsung dari sumber.

Jangan ragu untuk melakukannya, itu akan sangat bagus. Saya memposting masalah di webpack ts loader utama, seperti ts-loader, beberapa bulan yang lalu, dan saya telah diterima dengan sangat buruk...

Sebagai informasi, tidak ada masalah dengan plugin rollup TypeScript, sebagai bukti bahwa itu bisa dilakukan.

Saya gagal melihat apa gunanya ini sampai implementasi pemuat browser dan spesifikasi pemuat WGATWG mendukung setidaknya konfigurasi _some_ karena sebagian besar dependensi tidak akan dimuat dengan benar.

Dari sudut pandang saya, semua ini tidak penting sampai praktis untuk menggunakan pemuat asli pada impor yang merujuk ke penentu literal string arbitrer, sesuatu yang mungkin belum berupa URL, dan telah melalui transformasi yang menghasilkan URL sebenarnya.

Sampai saat itu kami akan tetap bergantung pada alat seperti SystemJS dan Webpack.

Saya membuat trafo kecil yang menghapus '.js' dari pernyataan impor/ekspor.
Saya menggunakan penjaga tipe tsutils , jadi yarn add tsutils --dev . (paket biasanya tetap diinstal jika Anda memiliki tslint dalam proyek Anda, jadi ketergantungan ekstra)

https://Gist.github.com/AviVahl/40e031bd72c7264890f349020d04130a

Dengan menggunakan ini, seseorang dapat menggabungkan file ts yang berisi impor dari file yang diakhiri dengan .js (menggunakan webpack dan ts-loader ), dan masih mentranspile sumber ke modul esm yang dapat dimuat browser (menggunakan tsc ).

Mungkin ada sejumlah kasus penggunaan di mana ini berguna.

EDIT: Saya memperbarui intinya untuk bekerja dengan ekspor juga. itu naif dan tidak dioptimalkan, tetapi berfungsi.

Ada gerakan tentang masalah ini?

Masalah ekstensi ini membawa kita kembali ke awal TypeScript dan mengapa tsconfig.json diperlukan dan mengapa opsi module ditambahkan ke pengaturan compilerOptions .

Karena masalah extension masalah ekstensi hanya untuk ES2015+ karena persyaratan dapat diselesaikan dengan cukup baik, biarkan ditambahkan oleh kompiler ketika kode yang ditargetkan adalah ES2015+.

  1. .js untuk .ts
  2. .jsx untuk .tsx

Halo, saya datang selarut ini tetapi ingin membantu. Saya mengalami kesulitan memahami apa masalahnya di sini. Dari contoh OP adalah:

import { ModalBackground } from './ModalBackground';

Apakah masalah yang kita tidak tahu apa './ModalBackground' itu? Itu bisa berupa folder atau yang lainnya?

Jika kita menjalankan tsc di seluruh proyek dan kita tahu bahwa ModalBackground.ts ada, maka kita akan tahu bahwa aman untuk menambahkan ekstensi, bukan?

Masalah ini juga menjadi perhatian komunitas RxJS. Bagaimana timeline solusi untuk ini? Apakah itu bahkan diprioritaskan? Apakah ada transformasi pihak ketiga yang akan membantu?

Saya tidak begitu yakin apakah ini masalah jika target keluarannya adalah ES2015 bukan? Ini mungkin termasuk dalam domain kemampuan browser ES2015. Terlebih lagi, @justinfagnani tidak bisakah kita mendorong ini sebagai tujuan platform yang perlu dikhawatirkan? (Mungkin perlu garpu ke utas terpisah).

Terlebih lagi, @justinfagnani tidak bisakah kita mendorong ini sebagai tujuan platform yang perlu dikhawatirkan? (Mungkin perlu garpu ke utas terpisah).

Ya, tentu saja banyak orang ingin agar platform tersebut mendukung beberapa bentuk penentu telanjang, tetapi faktanya saat ini tidak dan bahkan tidak ada proposal untuk menambahkannya. Kita harus melalui proses keseluruhan, kemungkinan multi-tahun.

Bahkan jika kita akhirnya mendapatkan dukungan bare-specifier, sangat kecil kemungkinannya bahwa itu akan dalam bentuk resolusi modul-simpul apa adanya. Jadi akan ada ketidakcocokan antara algoritma resolusi yang digunakan oleh tsc untuk menemukan file, dan algoritma resolusi yang digunakan oleh browser (dan bahkan mungkin dukungan modul asli node, afaik).

Akan sangat bagus jika tsc dapat memperbaiki jalur apa yang digunakannya untuk menemukan modul lain sehingga alat dan lingkungan hilir tidak menafsirkan penentu dengan pendapat yang bertentangan.

@justinfagnani mereka sudah ditafsirkan dengan pendapat yang bertentangan. TS menghasilkan file JS yang tidak ditunjuk oleh kode JS yang dihasilkannya. ES6 adalah hal yang paling dekat dengan cara yang benar secara resmi untuk melakukan JavaScript, jadi jika kode ES6 yang dihasilkan oleh TypesScript salah, ini adalah bug yang sederhana dan sederhana. Tidak perlu menunggu proposal dan semacamnya, cukup perbaiki bug TypeScript. Tetapi hari ini orang merasa bahwa jika mereka tidak menemukan kesalahan pada sesuatu dan memasukkannya ke dalam 10 lapisan proposal sebelum bertindak, maka mereka tidak bertindak secara intelektual. Beri aku istirahat.

@aluanhaddad Memang benar bahwa banyak proyek tidak akan mendapat manfaat, tetapi ada beberapa proyek yang tidak menggunakan dependensi npm (atau yang mampu menangani dependensi npm dalam beberapa cara), sehingga proyek tersebut akan mendapat manfaat.

Ini juga sangat berguna untuk perpustakaan TypeScript , yang dikompilasi ke ES6. Saat ini library tersebut tidak dapat digunakan secara native di browser, tetapi jika TypeScript mengeluarkan ekstensi .js maka library tersebut akan berfungsi.

@justinfagnani Belum distandarisasi atau diimplementasikan, tetapi ada proposal untuk membuat paket npm berfungsi di browser.

Peta nama paket dapat dibuat secara otomatis oleh kompiler TypeScript, atau dengan alat lain.

Jadi saya melihat kembali ini lagi, apakah ada solusi yang bagus untuk ini, selain dari skrip simpul saya?

Saya telah menggunakan solusi ini:
https://github.com/Microsoft/TypeScript/issues/16577#issuecomment -343610106

Tetapi saya percaya jika modul tidak memiliki ekstensi file tetapi disajikan dengan tipe MIME yang benar, itu harus diselesaikan.

Setiap gerakan ini?

mungkin https://github.com/Microsoft/TypeScript/pull/25073 bisa menyelesaikan ini?

@Kingwl Apakah Anda mendukung beberapa ekstensi file lain? seperti .mjs .es .esm .

mungkin tidak, ini fitur lain

Bagaimana ini bisa terjadi? Kompiler TypeScript _knows_ bahwa output target adalah file JS. Saya telah menjelajahi utas ini selama 15 menit dan saya masih tidak mengerti mengapa itu menghilangkan ekstensi.

Dengan jumlah referensi untuk masalah ini, saya berasumsi bahwa itu bergerak ke arah yang benar. Saya akan mencoba lagi segera.

Bagaimana ini bisa terjadi? Kompiler TypeScript _knows_ bahwa output target adalah file JS. Saya telah menjelajahi utas ini selama 15 menit dan saya masih tidak mengerti mengapa itu menghilangkan ekstensi.

Ada kasus penggunaan umum, yang digunakan orang, di mana kurangnya ekstensi memungkinkan infrastruktur yang lebih fleksibel. Node memerlukan kait dan pemuat webpack adalah dua kasus seperti itu.

Bagaimana ini bisa terjadi? Kompiler TypeScript _knows_ bahwa output target adalah file JS. Saya telah menjelajahi utas ini selama 15 menit dan saya masih tidak mengerti mengapa itu menghilangkan ekstensi.

Ada kasus penggunaan umum, yang digunakan orang, di mana kurangnya ekstensi memungkinkan infrastruktur yang lebih fleksibel. Node memerlukan kait dan pemuat webpack adalah dua kasus seperti itu.

Tidak ada yang peduli dengan modul browser.

Apakah itu hanya akan membunuh tim TypeScript untuk menambahkan tanda keikutsertaan untuk memancarkan ekstensi .js? Kami _do_ tahu apa yang kami lakukan di sini, atau tidak akan ada selusin utas (baik terbuka maupun tertutup) yang masih mengumpulkan balasan dan pertanyaan membingungkan. Kami mengerti itu bukan kekurangan dengan TS, tetapi jika TS ada di sini untuk menyelesaikan masalah JS kami, maka tambahkan kesengsaraan ini ke dalam daftar.

PENAFIAN:

Ya, saya mengerti ini dapat menyebabkan banyak orang memposting masalah di sini bahwa "Anda merusak webpack" tetapi sungguh, sangat sulit bagi orang-orang itu. Itu harus opt-in.

Btw, menggali melalui sumber TypeScript, saya melihat importModuleSpecifierEnding -- dapatkah ini (ab)digunakan untuk menyebabkan emitor menggunakan akhiran .js ?

Mungkin bubur proposal ini dengan skema tsconfig? https://github.com/domenic/package-name-maps

Pada titik ini saya akan senang jika TypeScript hanya dapat secara otomatis menulis ulang impor menggunakan paths yang ditentukan dalam tsconfig. Bahkan tanpa dukungan browser yang mungkin akan menyelesaikan sebagian besar masalah bagi saya.

Ada pembaruan? Adakah upaya untuk menyelesaikan masalah ini? Kami memiliki semua browser utama yang mendukung modul es secara default, standar untuk mereka yang memerlukan ekstensi untuk ada di sana. Saya mengerti kami dapat menambahkannya secara manual dan tsc akan mengerti itu, tetapi ini tidak wajib, mengapa itu tidak berfungsi?
Maaf untuk merengek tetapi masalah ini sudah sangat tua sekarang dan belum ada yang dilakukan ...

Bagaimana ini bisa terjadi? Kompiler TypeScript _knows_ bahwa output target adalah file JS. Saya telah menjelajahi utas ini selama 15 menit dan saya masih tidak mengerti mengapa itu menghilangkan ekstensi.

Ada kasus penggunaan umum, yang digunakan orang, di mana kurangnya ekstensi memungkinkan infrastruktur yang lebih fleksibel. Node memerlukan kait dan pemuat webpack adalah dua kasus seperti itu.

Kemudian, mungkin kompiler TypeScript dapat menerima opsi untuk menambahkan ekstensi atau tidak. Mungkin bahkan dapat menerima satu set regex untuk menambahkan (atau tidak) ekstensi, seperti opsi sertakan (https://www.typescriptlang.org/docs/handbook/tsconfig-json.html).

Ya, itu sudah diusulkan setidaknya sekali sebelumnya, mengapa tidak mempertimbangkannya? TS sudah memiliki beberapa fitur eksperimental yang mungkin berubah di masa mendatang setelah diterapkan di browser, tetapi TS sudah memiliki tanda untuk spesifikasi yang tidak stabil tersebut. Mengapa tidak memiliki flag eksperimental addImportsExtensions di mana ia hanya akan melakukan module += '.js' , itu saja! Tidak ada logika yang funky, tidak ada fitur tambahan. Ini bisa menjadi target yang berbeda jika Anda lebih suka menyimpannya sebagai target terpisah. Lebih dari itu, jika Anda menerima salah satu di atas saya pribadi akan menggali melalui kode tsc dan membuat PR untuk itu, hanya tidak ingin kehilangan waktu saya jika tidak akan diterima.

Anda cukup menggunakan transformasi khusus untuk menulis ulang impor dalam kode yang dipancarkan (menambahkan '.js' atau menggunakan jalur impor modul yang diselesaikan).

Cara Menulis Transformasi TypeScript
ttypescript: pembungkus untuk tsc yang menerapkan transformasi selama kompilasi

Mungkin sudah ada transformasi yang melakukan apa yang Anda butuhkan.

Saya tahu itu mungkin, saya telah sedikit bermain-main dengan compiler API (meskipun tidak sebanyak yang saya inginkan). Masalahnya, ia menambahkan alat tambahan ke proyek dan alat tambahan memiliki pengelola tambahan yang mungkin atau mungkin tidak menanggapi masalah dengan cukup cepat jika sama sekali (seringkali bukan karena kesalahan mereka, kita semua memiliki kehidupan dan pekerjaan). Proyek kecil sering ditinggalkan, dan melakukan semuanya sendiri hanya memindahkan tanggung jawab kepada kami, jadi alih-alih mengurus kode bisnis, kami menghabiskan waktu untuk perkakas.
Mempertimbangkan hal di atas, banyak proyek bahkan tidak akan menganggapnya sebagai solusi dan malah menambahkan langkah-langkah build tambahan seperti rollup dll, yang menambahkan overhead konfigurasi tambahan dan membuat kita kembali ke biaya pemeliharaan tambahan.
Singkatnya: Saya lebih suka menghabiskan waktu saya untuk PR daripada TS resmi, di mana saya dan komunitas akan mendapat manfaat darinya, daripada menghabiskannya untuk solusi khusus yang akhirnya bisa saya batalkan (dengan tidak punya waktu atau banyak alasan lain ), atau yang tidak dapat digunakan oleh siapa pun di dunia.

@ajafff ​​Ini bisa menjadi solusi, tapi saya pikir masalah utamanya adalah sebagai berikut: transpiler TypeScript menghasilkan kode sumber yang salah di browser. Ada baiknya melakukan transformasi, tetapi saya melihatnya sebagai solusi. Saya ingin tahu apakah saya harus peduli dengan detail transpilasi dan perlu mengimplementasikan transformasi saya sendiri atau sesuatu yang harus dikelola oleh kompiler.

Transformasi adalah alat yang sangat kuat, kita dapat menulis seluruh transpiler baru sebagai transformasi, tetapi saya pikir ini bukan cara yang benar.

Ya, itu sudah diusulkan setidaknya sekali sebelumnya, mengapa tidak mempertimbangkannya? TS sudah memiliki beberapa fitur eksperimental

TypeScript memiliki tepat satu flag eksperimental yang ditambahkan 3 tahun yang lalu, dan itu untuk proposal ECMAScript yang tidak lagi kompatibel dengan proposal saat ini.

transpiler TypeScript menghasilkan kode sumber yang salah di browser

Saya mengerti harapan Anda, tetapi mengingat bahwa kompiler tidak menulis ulang jalur yang Anda tulis, saya terkejut Anda tidak menganggap impor kode Anda sendiri "salah". 😉.

Maaf @DanielRosenwasser , pernahkah Anda mendengar sesuatu yang disebut npm? Orang-orang memposting paket mereka di sana sehingga kita semua dapat menggunakannya. Saya mengerti Anda mungkin menganggap saya sangat tinggi, tetapi sayangnya saya bukan penulis sebagian besar dari mereka, jadi saya tidak dapat mengeditnya dengan menambahkan ekstensi.
Jika proyek saya hanya menggunakan kode saya, saya akan lebih berterima kasih atas apa yang dibawa TypeScript, karena itu benar-benar tangan kanan saya dalam pengkodean (selain WebStorm). Namun saya menggunakan paket pihak ke-3 seperti yang saya pikir sebagian besar dari kita dan itu tidak harus berisi ekstensi. Beberapa proyek, seperti rxjs, benar-benar menunggu dengan harapan bahwa TypeScript akan menyediakan cara untuk menambahkan ekstensi, jika tidak, itu akan mengharuskan mereka untuk mengubah seluruh proses pembuatan, jadi kami kembali menghabiskan waktu ekstra untuk alat alih-alih produk.
Sekarang tolong, bisakah kamu menjawab 3 pertanyaan?

  1. Apakah tim TypeScript bersedia mengirimkan fitur ini?
  2. Jika ya, apakah Anda akan menerima PR?
  3. Jika tidak, kapan Anda berencana merilis ini?

Jika jawaban untuk pertanyaan pertama adalah 'tidak', tolong, tutup masalah ini dengan menyatakan secara resmi bahwa Anda TIDAK bersedia mengirimkan fitur ini, jangan membuat orang lain menunggu jika tidak datang.

Ya, itu sudah diusulkan setidaknya sekali sebelumnya, mengapa tidak mempertimbangkannya? TS sudah memiliki beberapa fitur eksperimental

TypeScript memiliki tepat satu flag eksperimental yang ditambahkan 3 tahun yang lalu, dan itu untuk proposal ECMAScript yang tidak lagi kompatibel dengan proposal saat ini.

transpiler TypeScript menghasilkan kode sumber yang salah di browser

Saya mengerti harapan Anda, tetapi mengingat bahwa kompiler tidak menulis ulang jalur yang Anda tulis, saya terkejut Anda tidak menganggap impor kode Anda sendiri "salah". 😉.

Ini adalah poin yang bagus @DanielRosenwasser , saya hanya menganggap kode saya sendiri dengan benar karena sepertinya membaca spesifikasi TypeScript (https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md#11.3) benar.

Saya cukup yakin Anda telah membaca spesifikasi ECMAScript. Dalam spesifikasi tidak ditentukan apakah modul harus diakhiri dengan ekstensi atau tidak. Dalam spesifikasi, impor modul diselesaikan menggunakan algoritma HostResolveImportedModule, tetapi definisinya ambigu. Masalahnya bukan pada spesifikasi ECMAScript. Masalahnya adalah browser menyelesaikan modul seolah-olah [ModuleRequest] seperti yang didefinisikan dalam spesifikasi adalah jalur ke sumber daya.

Dengan mengingat hal ini, cukup buka halaman beranda bahasa: https://www.typescriptlang.org/ .

Di footer halaman Anda dapat membaca baris berikut:

Dimulai dan diakhiri dengan JavaScript

TypeScript dimulai dari sintaks dan semantik yang sama yang diketahui jutaan pengembang JavaScript saat ini. Gunakan kode JavaScript yang ada, gabungkan pustaka JavaScript populer, dan panggil kode TypeScript dari JavaScript.

TypeScript dikompilasi untuk membersihkan, kode JavaScript sederhana yang berjalan di browser apa pun , di Node.js, atau di mesin JavaScript apa pun yang mendukung ECMAScript 3 (atau yang lebih baru).


Anda menjanjikan kode yang berjalan di setiap browser, tetapi tampaknya tidak benar, itu sebabnya masalah ini tetap ada selama lebih dari setahun.

Seperti yang ditunjukkan @Draccoz , kami hanya ingin tahu apa yang Anda lakukan dengan masalah ini. Tapi agak frustasi untuk membaca satu hal di halaman rumah Anda dan sebaliknya dalam masalah ini.

Tidak, kami tidak bersedia mengirimkan apa pun yang terkait dengan ini sampai setidaknya ada kejelasan seputar hal-hal seperti ES interop di Node dan strategi yang masuk akal untuk mengirimkan dependensi transitif yang akan Anda gunakan dari npm sejak awal. Jika Anda tidak menggunakan TypeScript, Anda akan memiliki masalah yang sama seputar manajemen dependensi dan resolusi, jadi tidak masuk akal bagi kami untuk menemukan sesuatu yang dapat dikembangkan secara mandiri oleh ekosistem JS secara luas. Tetapi bahkan jika masalah itu diselesaikan, saya tidak dapat menjamin bahwa kami akan membuat perubahan apa pun di sini.

Anda menjanjikan kode yang berjalan di setiap browser, tetapi tampaknya tidak benar, itu sebabnya masalah ini tetap ada selama lebih dari setahun.

Saya pikir interpretasi ini terlalu literal. var fs = require('fs') tidak berfungsi saat Anda menjalankannya di browser, HTMLDivElement tidak ditentukan di Node, dan String.prototype.startsWith tidak berfungsi di browser lama. Untuk mengatasi ini, orang telah membuat alat dan pustaka/polyfill di luar TypeScript karena mereka berlaku untuk ekosistem JavaScript yang lebih luas.

Jadi bisakah Anda menutup masalah ini? Ini adalah pemblokir untuk proyek lain yang menunggu TS untuk melakukannya atau menyatakan Anda tidak melakukannya. Jika Anda tidak bisa hanya menambahkan tanda sederhana, tutup masalah ini dan beri tahu orang lain tentang keputusan Anda.

@DanielRosenwasser Terima kasih atas tanggapan cepat Anda, saya sangat menghargai itu. Saya pikir itu pilihan yang bijaksana.

Saya pikir interpretasi ini terlalu literal. var fs = require('fs') tidak berfungsi saat Anda menjalankannya di browser, HTMLDivElement tidak didefinisikan di Node, dan String.prototype.startsWith tidak berfungsi di browser lama. Untuk mengatasi ini, orang telah membuat alat dan pustaka/polyfill di luar TypeScript karena mereka berlaku untuk ekosistem JavaScript yang lebih luas.

Tentu saja, tapi apa lagi yang bisa dipikirkan orang yang tidak tahu apa-apa tentang TypeScript? Fakta bahwa interpretasi saya terlalu literal sama benarnya dengan fakta bahwa teks ini dapat "membingungkan" siapa pun yang tidak tahu apa-apa tentang TypeScript .

Mungkin Anda dapat memperbarui dokumen Anda (https://www.typescriptlang.org/docs/handbook/modules.html) untuk mencerminkan perilaku yang sebenarnya.

@DanielRosenwasser sekali lagi terima kasih atas tanggapan Anda. Saya telah menunggu sesuatu yang serupa selama setahun.

Alasan saya menginginkan fitur ini adalah agar saya dapat melihat aplikasi web seperti apa yang dapat saya buat tanpa alat bantu apa pun. Sampai saat itu saya dapat menggunakan skrip yang saya tulis sebelumnya.

Untuk orang-orang seperti saya yang mencari solusi untuk dapat menggunakan modul ES dan TypeScript di browser hari ini, saya menemukan https://github.com/guybedford/es-module-shims. Ini bertindak sebagai semacam polyfill untuk peta nama paket sementara kami menunggu finalisasi spesifikasi dan implementasi browser. Ini memecahkan masalah @QuantumInformation yang ingin tidak menggunakan alat build apa pun (masalah saya juga) ketika membuat aplikasi web sederhana di TypeScript (selain dari kompiler TS).

import 'knockout'

export class MyViewModel {
    greeting: KnockoutObservable<string>
    target: KnockoutObservable<string>
    constructor() {
        this.greeting = ko.observable('hello')
        this.target = ko.observable('world')
    }
}
<!DOCTYPE html>


md5-f28d4b503a1603c40bfeb342f341bfbe


<main>
    <span data-bind='text: `${greeting()} ${target()}`'></span>
    <script type='module-shim'>
        import 'knockout'
        import { MyViewModel } from 'index'
        ko.applyBindings(new MyViewModel())
    </script>
</main>

Secara teori, setelah peta nama paket didukung oleh browser, Anda dapat menemukan/mengganti type='module-shim' dengan type='module' dalam file HTML Anda dan mengubah skrip peta paket menjadi apa pun yang akhirnya diselesaikan untuk penyertaan peta paket di spesifikasi

Mungkin juga perlu diperhatikan bahwa ekstensi .js tidak diamanatkan oleh browser atau apa pun - Anda selalu dapat mengonfigurasi server web Anda menjadi lebih unpkg -seperti dan menyajikan file .js dari URL permintaan tanpa ekstensi. Semuanya dapat dikonfigurasi di sisi server web.

@weswigham itu bisa sangat bermasalah, karena tsc (dan resolusi modul simpul klasik) akan tahu bahwa ./foo dan ./foo.js merujuk ke file yang sama, tetapi browser akan memperlakukannya berbeda, bahkan jika pengalihan server web. Anda harus yakin bahwa Anda merujuk ke file dengan cara yang persis sama di setiap impor.

Omong-omong, masalah ini tidak mencegah modul yang dihasilkan TypeScript untuk digunakan di browser saat ini. Selalu impor file dengan ekstensi .js . tsc melakukan hal yang benar dan menyelesaikan jenis dari file .ts , dan Anda mendapatkan kompatibilitas browser.

@weswigham Ingatlah bahwa ada situasi di mana Anda menyajikan file tanpa memiliki akses ke server web. GitHub Pages, IPFS, S3, dll. Dengan munculnya kerangka kerja aplikasi satu halaman, menjadi semakin umum untuk menjalankan "tanpa server" (di mana tanpa server di sini berarti tanpa server yang Anda kendalikan/konfigurasi untuk melayani aset Anda), jadi Anda tidak dapat mengandalkan filter sisi server untuk melayani apple.js ketika permintaan dibuat untuk apple .

Anda harus yakin bahwa Anda merujuk ke file dengan cara yang persis sama di setiap impor.

Selalu dapat membuat satu atau 404 lainnya tergantung pada preferensi penulisan Anda. Jika Anda menggunakan symlink dalam proyek Anda, mereka akan menyebabkan masalah serupa yang harus Anda pilih juga bagaimana menanganinya.

Selalu impor file dengan ekstensi .js

Ya, itu juga berfungsi dengan baik.

@QuantumInformation Apakah cuplikan Anda yang digunakan di sini adalah untuk penggunaan terbuka? Bisakah saya menggunakannya dalam sebuah proyek? 😃.

@disstante ya Anda bisa menggunakannya

FYI jika Anda menggunakan Jest untuk menguji dan mengubah ekstensi ke .js di sumbernya - itu rusak
tetapi Anda dapat menambahkan yang berikut ini ke konfigurasi lelucon Anda untuk memperbaikinya

  "jest": {
    ...
    "moduleNameMapper": {
      "(.*)\\.js": "$1"
    }
  }

Halo @MrAntix ,

Saya pikir lelucon adalah perpustakaan yang harus beradaptasi dengan TypeScript, bukan sebaliknya.

Saya memiliki situs lain yang tidak ingin saya gunakan dengan alat build. Apakah ini yang terbaik dari kami:

https://github.com/microsoft/TypeScript/issues/16577#issuecomment -452312753

Sebagai solusinya, Anda bisa melakukannya seperti ini (walaupun ini file ts, bukan js)

Screenshot 2019-06-05 at 22 47 49

Jika ada yang ingin mencobanya:
https://github.com/QuantumInformation/web-gen-bot

Namun, saya tidak bisa mendapatkan debugging sumber untuk bekerja dengan tsconfig saat ini, akan melaporkan kembali.

Pada akhirnya saya kembali ke webpack, node_modules adalah pembunuh ketika mencoba untuk menjauh dari membangun alat di browser.

Bukan hanya Jest -- jika Anda menggunakan tsc untuk mengkompilasi TypeScript sebelum menerbitkan, modul JS apa pun yang mengimpor paket yang dihasilkan akan rusak karena perbedaan resolusi modul.

Diskusi di sini tampaknya telah bercabang sedikit menjadi dua masalah terkait tetapi pada akhirnya terpisah:

  • TypeScript harus menghasilkan file yang dapat dimuat secara asli di browser
  • TypeScript harus memecahkan fakta bahwa jalur modul node tidak selalu merupakan URL yang valid.

Saya pikir kita perlu fokus pada masalah pertama, karena yang kedua jelas merupakan sesuatu yang tidak dapat diselesaikan oleh TypeScript dengan sendirinya.

Masalah pertama, bagaimanapun, adalah sesuatu yang TypeScript dapat selesaikan dan harus diprioritaskan, karena ini adalah pemblokir utama bagi kebanyakan orang yang ingin menggunakan TypeScript untuk membangun aplikasi web yang ditargetkan pada browser modern.

Menurut pendapat saya, masalahnya bermuara pada ini:

Jika menjalankan tsc menghasilkan satu file dengan ekstensi .js dan kemudian file lain yang mengimpor file .js pertama, tidak ada ambiguitas tentang ekstensi apa yang akan digunakan, dan harus ada opsi untuk menyertakan ekstensi.

Untuk semua pernyataan impor yang menunjuk ke file selain file yang dihasilkan TypeScript, saya pikir tidak masalah untuk membiarkannya tidak berubah (seperti yang dilakukan Typescript hari ini).

Sesuai opsi pertama, saya pikir arg baris perintah akan menjadi yang terbaik, dan itu akan mati secara default. Saya mengatakan ini karena, jika saya menggunakan webpack, saya tidak ingin .js ditambahkan ke impor karena webpack menangani bundling modul.

Bagaimanapun, node_modules adalah pembunuh yang menghentikan saya menggunakan peretasan untuk aplikasi browser modul asli.

Saya mengatakan ini karena, jika saya menggunakan webpack, saya tidak ingin .js ditambahkan ke impor karena webpack menangani bundling modul.

Webpack menangani ekstensi .js dengan sangat baik, jadi tidak ada perbedaan.

Bahkan terkadang perlu menggunakan .js dengan Webpack (dalam situasi di mana ada beberapa file dengan nama yang sama tetapi ekstensi yang berbeda).

Jadi bisakah Anda menjelaskan lebih lanjut tentang mengapa Anda tidak ingin .js diimpor dengan Webpack?

Ketika saya mengatakan I don't want maksud saya saya tidak perlu untuk kasus penggunaan saya.

Saya tidak melihat alasan kuat mengapa itu bukan perilaku default (selalu enggan untuk menambahkan flag konfigurasi lain ...)

Menyetel impor ke .js menyebabkan ts-node berhenti bekerja dengan benar untuk file tersebut. Ini karena ts-node hanya mengkompilasi satu file pada satu waktu dan jika konten file yang dipancarkan berakhir dengan require('./foo.js') maka ketika nodejs memproses file itu, ia akan mencoba memuat ./foo.js yang tidak ada di mana saja di disk dan karenanya akan gagal. Ketika kode memang membutuhkan( ./foo ) di sisi lain, handler ts-node akan dipanggil pada titik mana ia dapat mengkompilasi ./foo.ts ke dalam JS dan mengembalikannya.

Jika TypeScript mengeluarkan ekstensi .js dalam semua kasus, ts-node akan mengalami masalah yang sama. Namun, jika ada opsi untuk mengaktifkan apakah ekstensi ditambahkan secara otomatis atau tidak, maka ts-node dapat menonaktifkan opsi kompiler tersebut, yang akan memungkinkan sistem saat ini untuk terus bekerja.

Karena Node.js --experimental-modules memerlukan ekstensi file wajib, API untuk ini sangat mudah tanpa memerlukan analisis ketergantungan - opsi seperti --jsext dapat menulis ulang ekstensi .ts menjadi .js ekstensi .ts seperti import 'npmpkg.ts' . Kasus ini sangat jarang, tetapi untuk menanganinya secara komprehensif dalam resolusi, aturannya adalah membuat pengecualian untuk _bare specifiers_ di sepanjang baris - jika penentu telanjang (bukan URL, atau jalur relatif) adalah nama paket npm yang valid ( cocok /^(@[-_\.a-zA-Z\d]+\/)?[-_\.a-zA-Z\d]+$/ , dari https://github.com/npm/validate-npm-package-name ), lalu abaikan ekstensi .ts dalam penulisan ulang.

Saya telah membuat transformator kompiler TypeScript yang akan menambahkan ekstensi file .js ke semua jalur impor relatif. Ini berarti jika file .ts Anda memiliki import { Foo } from './foo' itu akan memancarkan import { Foo } from './foo.js' . Ini tersedia di NPM, dan instruksi tentang cara menggunakannya dapat ditemukan di readme proyek.

https://github.com/Zoltu/typescript-transformer-append-js-extension

Jika sesuatu seperti ini diintegrasikan ke dalam kompiler TypeScript (sebagai opsi kompiler), mungkin sebaiknya lebih cerdas dalam memutuskan kapan harus menambahkan ekstensi .js dan kapan tidak. Saat ini ia mencari jalur apa pun yang dimulai dengan ./ atau ../ dan yang tidak memiliki . di tempat lain di jalur tersebut. Ini berarti itu tidak akan melakukan hal yang benar dalam sejumlah skenario kasus Edge, meskipun saya mempertanyakan apakah ada orang _sebenarnya_ akan mengalami kasus Edge tersebut atau tidak.

@MicahZoltu senang melihat solusi userland untuk ini. Saya pikir itu cukup penting meskipun model mental menjadi selalu menyertakan ekstensi file , sehingga opsi ekstensi TypeScript dapat menjadi _mengubah ekstensi .ts menjadi ekstensi .js pada compile_. Itu menghindari kasus tepi resolusi, hanya menyisakan kasus nama paket npm yang kebetulan berakhiran ".ts", yang dapat ditangani seperti yang saya diskusikan di komentar saya sebelumnya.

@guybedford Menyertakan ekstensi .js dalam file .ts membuat file tidak dapat dieksekusi di ts-node. Memecahkan masalah di ts-node jauh dari non-sepele karena cara NodeJS melakukan resolusi file. Ini berarti bahwa jika Anda menerbitkan perpustakaan dengan ekstensi .js hard-coded, perpustakaan tidak akan berfungsi untuk siapa pun yang menggunakan ts-node. Lihat diskusi tentang ini di https://github.com/TypeStrong/ts-node/issues/783.

@MicahZoltu Maksud saya termasuk ekstensi .ts dalam file .ts .

@guybedford Menyertakan ekstensi .js dalam file .ts membuat file tidak dapat dieksekusi di ts-node.

Ini adalah alasan lain mengapa mengeksekusi otomatis TypeScript di node dan browser adalah ide yang buruk.

@MicahZoltu Maksud saya termasuk ekstensi .ts dalam file .ts.

Saya pikir masalahnya adalah ini merusak kesetaraan antara file .ts dan pasangan .js / .d.ts . Ini berarti bahwa jika Anda mengimpor file yang dikompilasi dengan proyek saat ini, Anda menggunakan .ts , dan jika Anda memindahkan file ke proyek lain, Anda perlu mengubah impor untuk menggunakan .js .

Ini juga berarti bahwa output tidak berfungsi di lingkungan standar tanpa transformator. Mengingat bahwa tidak ada cara untuk menginstal transformator dari file .tsconfig , itu berarti Anda harus selalu menggunakan kompiler khusus. Itu adalah penghalang yang cukup besar untuk diterapkan demi keuntungan kecil menggunakan .ts daripada .js .

Ini berarti bahwa jika Anda mengimpor file yang dikompilasi dengan proyek saat ini, Anda menggunakan .ts, dan jika Anda memindahkan file ke proyek lain, Anda perlu mengubah impor untuk menggunakan .js.

Batas impor eksternal / internal adalah hal-hal yang terdefinisi dengan baik. Jika ketergantungan berpindah dari file .ts internal dari build yang sama saat ini, menjadi file .js eksternal dari impor paket lain yang memiliki build terpisah atau mungkin bukan TypeScript , maka ya, Anda harus mengubah ekstensi karena ini adalah konsep yang sama sekali berbeda.

Ini juga berarti bahwa output tidak berfungsi di lingkungan standar tanpa transformator.

Meskipun sebuah transformator dapat membantu kita menjelajahi ini, --ts-to-js atau flag/opsi kompiler serupa sangat diperlukan untuk menyelesaikan masalah ini.

@guybedford Anda meyakinkan saya bahwa memasukkan .ts adalah hal yang benar untuk dilakukan untuk plugin. Namun, setelah mencoba menerapkannya, saya mengetahui bahwa TypeScript sebenarnya tidak mengizinkannya!

// foo.ts
export function foo() { console.log('foo') }
// bar.ts
import { foo } from './foo.ts' // Error: An import path cannot end with a '.ts' extension. Consider importing './foo' instead
foo()

Halo, Bagaimana dengan ini?


memasukkan:

// src/lib.js.ts
export const result = 42;
// src/index.js.ts
import { result } from "./lib.js";

console.log(result);

keluaran:

// build/lib.js
export const result = 42;
// build/index.js
import { result } from "./lib.js";

console.log(result);

edisi #30076

Satu-satunya ekstensi .ts pada file TypeScript terasa paling tepat bagi saya. Seringkali Anda tidak tahu sampai waktu kompilasi apa targetnya. Misalnya, di banyak proyek perpustakaan saya, saya memiliki beberapa file tsconfig.json yang menargetkan lingkungan yang berbeda, seperti menargetkan browser modern yang seharusnya mengeluarkan file .js dan memetakan jalur impor ke .js , atau menargetkan Node modern, yang seharusnya memancarkan file .mjs dan memetakan jalur impor ke .mjs .

@MicahZoltu bahwa mengimpor file yang diakhiri dengan .ts adalah kesalahan mungkin untuk keuntungan kita sebenarnya. Karena ini berarti penulisan ulang ekstensi .ts ke .js pada kompilasi dapat ditambahkan setiap kali ekstensi .ts digunakan tanpa memerlukan tanda :)

Mungkin PR untuk mengaktifkan ekstensi .ts tambahan yang didukung dan ditulis ulang menjadi ekstensi .js (mungkin di bawah tanda untuk mengaktifkan fitur ini, tetapi tanda yang dapat dihapus tepat waktu) akan menjadi cara yang bagus untuk memulai di sepanjang jalan ini.

//cc @DanielRosenwasser

Masalah ini sudah sangat lama sehingga seseorang mungkin sudah mengatakan ini, jadi berisiko mengulangi apa yang telah dikatakan:

TypeScript harus mengizinkan pengembang untuk menentukan ekstensi dalam import s karena itu adalah JavaScript yang valid. Dan ini bukan hanya tentang ekstensi JS/TS! Di ESM, ekstensi apa pun valid selama tipe MIME benar.

import actuallyCode from './lookLikeAnImage.png';

…harus valid selama server menyajikan JavaScript yang valid dalam file itu dan menyetel jenis MIME yang benar. Ini lebih jauh karena hal yang sama berlaku untuk TS! File TS dapat berupa kode sumber JS yang disajikan dengan tipe JS MIME dan jalur yang valid untuk impor modul ESM.

IMO TypeScript seharusnya hanya mempertimbangkan impor tanpa ekstensi (seperti yang diinginkan Anda hari ini) dan membiarkannya sendiri, tanpa kesalahan, peringatan, dll. Jika tidak, ia menolak kode JavaScript yang valid yang sangat disayangkan untuk sesuatu yang mengklaim sebagai superset dari JS.

Maaf jika ini bukan tempat yang tepat untuk mengangkat ini, saya melihat beberapa masalah lain: #18971, #16640, #16640 tetapi masalah tentang topik ini tampaknya semakin tertutup kiri dan kanan jadi saya menganggap ini adalah yang "utama" karena dibiarkan tetap terbuka.

Bermain dengan NodeJS v12.7.0

salathiel@salathiel-genese-pc:~/${PATH_TO_PROJECT}$ node --experimental-modules dist/spec/src/ioc
(node:15907) ExperimentalWarning: The ESM module loader is experimental.
internal/modules/esm/default_resolve.js:59
  let url = moduleWrapResolve(specifier, parentURL);
            ^

Error: Cannot find module '${PROJECT_ROOT}/dist/spec/src/ioc' imported from ${PROJECT_ROOT}/
    at Loader.resolve [as _resolve] (internal/modules/esm/default_resolve.js:59:13)
    at Loader.resolve (internal/modules/esm/loader.js:73:33)
    at Loader.getModuleJob (internal/modules/esm/loader.js:149:40)
    at Loader.import (internal/modules/esm/loader.js:133:28)
    at internal/modules/cjs/loader.js:830:27
    at processTicksAndRejections (internal/process/task_queues.js:85:5) {
  code: 'ERR_MODULE_NOT_FOUND'
}
salathiel@salathiel-genese-pc:~/${PATH_TO_PROJECT}$ node --experimental-modules dist/spec/src/ioc.js
(node:16155) ExperimentalWarning: The ESM module loader is experimental.
internal/modules/esm/default_resolve.js:59
  let url = moduleWrapResolve(specifier, parentURL);
            ^

Error: Cannot find module '${PROJECT_ROOT}/dist/spec/src/observe' imported from ${PROJECT_ROOT}/dist/spec/src/ioc.js
    at Loader.resolve [as _resolve] (internal/modules/esm/default_resolve.js:59:13)
    at Loader.resolve (internal/modules/esm/loader.js:73:33)
    at Loader.getModuleJob (internal/modules/esm/loader.js:149:40)
    at ModuleWrap.<anonymous> (internal/modules/esm/module_job.js:43:40)
    at link (internal/modules/esm/module_job.js:42:36) {
  code: 'ERR_MODULE_NOT_FOUND'
}

Sekarang, saya tidak yakin mengapa ini mengganggu ...

Saat ini TypeScript tidak menulis ulang jalur. Ini benar-benar menjengkelkan, tetapi saat ini Anda dapat menambahkan ekstensi .js sendiri.

@DanielRosenwasser https://github.com/microsoft/TypeScript/issues/16577#issuecomment -309169829

Bagaimana dengan penerapan di balik opsi? Suka --rewrite-paths ( rewritePaths: true ) ?

@ viT-1 Berikut ini adalah solusi untuk saat ini: https://github.com/microsoft/TypeScript/issues/16577#issuecomment -507504210

@MicahZoltu Saya baru saja menyelesaikan usecase saya dengan bundling SystemJS (opsi tsconfig outFile)

Saya belum membaca setiap komentar yang ditulis orang tentang ini, tetapi saya tidak tahu mengerti mengapa saya harus menulis .js trilyun kali. Saya ingin komputer melakukannya untuk saya.

@richardkazuomiller Kita semua melakukannya, tetapi @DanielRosenwasser menyatakan di https://github.com/microsoft/TypeScript/issues/16577#issuecomment -448747209 bahwa mereka tidak mau melakukan itu untuk saat ini (saya terkejut masalah ini masih terbuka menyesatkan untuk waktu yang lama setelah pernyataan di atas). Jika Anda ingin komputer melakukannya untuk Anda, pertimbangkan untuk menggunakan bundler atau alat pihak ketiga untuk menangani penulisan ulang jalur impor.

Siapa yang ingin saya menutup masalah ini?

Tolong jangan tutup, saya masih menunggu untuk melihat bagaimana tim TypeScript akan menanggapi bagaimana mereka akan mendekati impor ESM yang memungkinkan ekstensi apa pun untuk digunakan dan mengandalkan tipe MIME sebagai gantinya. Saat ini ini dimungkinkan dalam JavaScript tetapi tidak dalam TypeScript. (Silakan lihat komentar saya sebelumnya untuk detailnya.)

@TomasHubelbauer Inilah mengapa saya mengusulkan sebuah flag di file konfigurasi, ini bisa menunjukkan bahwa semua impor tanpa ekstensi harus memiliki ekstensi .js (atau yang dikonfigurasi lainnya). Ini akan menjadi pilihan, jadi defaultnya bisa salah, membuat proyek atau proyek yang ada dengan kebutuhan yang berbeda berfungsi sebagaimana adanya.

Seperti yang dikatakan sebelumnya:

Tidak yakin versi TS mana yang menambahkannya, tetapi impor seperti ' ./file.js' sekarang berfungsi (bahkan jika file sebenarnya adalah file.ts).
TypeScript menyelesaikan file dengan baik, dan mengeluarkan impor .js lengkap ke target.

Ini masuk akal karena setiap JavaScript yang valid adalah TypeScript yang valid. Karena Anda dapat melakukan:

import foo from './bar.js'

...di JS, Anda juga harus bisa melakukannya di TS. Jika Anda melakukannya, Anda memecahkan masalah penggunaan modul ES6 asli karena ekstensi Anda sudah benar.


Jangan lupa juga bahwa ketika browser melihat impor untuk ./foo/bar , itu sebenarnya membuat permintaan untuk itu. Fakta bahwa tidak ada yang disajikan adalah karena server. Anda dapat mengonfigurasinya sedemikian rupa sehingga permintaan untuk /foo/bar dipenuhi /foo/bar.js . Tidak mengatakan ini adalah solusi yang baik, atau bahkan ide yang bagus , tetapi secara teknis akan berhasil.

flag dalam file konfigurasi, ini dapat menunjukkan bahwa semua impor tanpa ekstensi harus memiliki ekstensi .js (atau yang dikonfigurasi lainnya) ditambahkan

Ini akan memecahkan sebagian besar kasus. Apakah tim TypeScript bersedia mempertimbangkan PR untuk opsi konfigurasi ini?

NodeJS sekarang _secara default_ berperilaku dengan cara yang sama seperti browser dalam hal resolusi modul jalur relatif. Itu tidak akan lagi menyimpulkan ekstensi .js secara default. Ini berarti bahwa perilaku TSC saat ini menghasilkan JS yang tidak valid di semua konteks runtime. Sepertinya masalah ini sekarang harus diatasi karena ada kejelasan pada browser dan perilaku NodeJS untuk ESM.

https://nodejs.org/api/esm.html#esm_customizing_esm_specifier_resolution_algorithm

Penyelesai baru untuk esm memerlukan mode resolusi baru - moduleResolution: node sebenarnya hanyalah penyelesai cjs untuk apa yang sekarang dapat saya sebut "simpul versi lama". Jika Anda ingin menargetkan resolver esm baru, kami memerlukan mode resolusi baru agar lebih cocok. Terutama karena node masih sepenuhnya mendukung resolver lama di semua konfigurasi yang ada. (Perhatikan: membuat penyelesai baru _default_ kami akan sulit)

Meskipun! Meskipun ada _ketidaksepakatan_ tentang hal itu dan _beberapa orang akan memilih untuk menyatakan pendapat sebagai fakta_, masih ada tanda --es-module-specifier-resolution=node yang mengembalikan perilaku ekstensi yang diharapkan dan mungkin masih menjadi default - seperti yang dikatakan dokumen, meskipun tidak ditandai , es modul dalam simpul _masih bersifat eksperimental_.

Juga, sebagai pengingat untuk permintaan awal: kami tidak menulis ulang impor. Pernah. Sama sekali. Penentu masuk === penentu keluar. Penentu menjelaskan maksud struktural, dan bukan tujuan kami untuk secara implisit memetakan dari satu struktur yang dimaksudkan ke yang lain. Anda juga dapat memikirkannya seperti ini: Jika Anda menulis const varFoo = "./Foo"; import(varFoo) apakah kami akan menambahkan ekstensi di sana, jika diperlukan? Tidak - itu konyol - untuk menangani semua bentuk input dinamis, kita perlu membungkus impor dinamis saat runtime, dan tiba-tiba kita menjadi pemuat modul kita sendiri, lapisan di atas pemuat platform bawaan. Sebagai gantinya, kami akan menyediakan mode resolver yang error dengan tepat saat Anda menghilangkan ekstensi (yang, tentu saja, Anda pasti sudah dapat menemukan aturan lint untuknya).

Jika Anda menemukan utas ini dan Anda _sangat ingin_ sumber input Anda tidak memiliki ekstensi, dan Anda _sangat membutuhkan_ output Anda untuk tetap berfungsi dengan itu saat menargetkan (simpul es) modul, Anda harus memberikan umpan balik di https://github.com/ nodejs/modules/issues/323 dengan alasan Anda, sehingga dapat bekerja seperti itu di platform target itu sendiri, karena pada akhirnya itulah yang kami tunda.

tiba-tiba kita menjadi pemuat modul kita sendiri

Bukankah tsc harus menjadi pemuat modul yang fungsional, apa pun yang terjadi? Anda tidak dapat mengetik-memeriksa impor jika Anda tidak dapat menemukan modul asalnya. Saya hanya ingin melihat semua berbagai pemuat modul berperilaku dengan cara yang kompatibel secara luas, atau setidaknya dengan cara yang dapat diprediksi berbeda yang cukup mudah untuk diakomodasi.

NodeJS sekarang secara default berperilaku dengan cara yang sama seperti browser dalam hal resolusi modul jalur relatif. Ini tidak akan lagi menyimpulkan ekstensi .js secara default. Ini berarti bahwa perilaku TSC saat ini menghasilkan JS yang tidak valid di semua konteks runtime.

Bukankah ini alasan lain untuk hanya menggunakan ekstensi file .js di specifier seperti yang sudah didukung oleh TypeScript? Itu menyelesaikan semuanya kecuali bahwa akan lebih bagus jika tsc melakukan kesalahan pada impor tanpa ekstensi.

Bukankah tsc harus menjadi pemuat modul fungsional apa pun yang terjadi? Anda tidak dapat mengetik-memeriksa impor jika Anda tidak dapat menemukan modul asalnya. Saya hanya ingin melihat semua berbagai pemuat modul berperilaku dengan cara yang kompatibel secara luas, atau setidaknya dengan cara yang dapat diprediksi berbeda yang cukup mudah untuk diakomodasi.

Kami tidak bertujuan untuk menyediakan implementasi pemuat waktu proses - hanya analisis waktu kompilasi yang mencerminkan pemuat waktu proses apa pun yang Anda targetkan. Kami tidak mungkin memetakan ulang semua impor tanpa komponen runtime, yang tidak kami miliki, atau ingin kami miliki.

Bukankah tsc harus menjadi pemuat modul fungsional apa pun yang terjadi?

Tidak saat runtime. tsc perlu memahami bagaimana runtime pilihan akan menyelesaikan penentu dan mengimplementasikannya pada waktu build, tetapi runtime murni diserahkan kepada lingkungan.

Anda juga dapat memikirkannya seperti ini: Jika Anda menulis const varFoo = "./Foo"; import(varFoo) apakah kami akan menambahkan ekstensi di sana, jika diperlukan?

@weswigham Ini adalah argumen yang kuat mengenai impor dinamis, tapi saya tidak _think_ Anda dapat melakukannya dengan impor statis? Saya dapat menghargai argumen bahwa strateginya harus sama untuk keduanya, tetapi saya pikir perlu disebutkan bahwa impor statis memenuhi peran yang sangat berbeda dari impor dinamis dan saya tidak berpikir itu _tidak masuk akal_ untuk memiliki strategi yang berbeda untuk statis penulisan ulang impor dan penulisan ulang impor dinamis.

Bukankah ini alasan lain untuk hanya menggunakan ekstensi file .js di penentu seperti yang sudah didukung oleh TypeScript? Itu menyelesaikan segalanya kecuali bahwa akan lebih bagus jika tsc melakukan kesalahan pada impor tanpa ekstensi.

@justinfagnani Ada dua masalah dengan itu:

  1. Waktu proses yang mengeksekusi TS secara asli (seperti TS-Node) akan gagal berfungsi jika Anda menentukan ekstensi .js pada impor Anda.
  2. Anda berbohong kepada kompiler (IMO) jika Anda menyertakan ekstensi .js dalam impor Anda.

Mengenai (2), jika saya memiliki dua file TS a.ts dan b.ts dan a.ts tidak import ... from './b.js' , saya memberi tahu kompiler" Saya memiliki file saudara bernama b.js . Pernyataan ini tidak benar. Lebih buruk lagi, jika Anda memiliki .b.ts dan b.js (yang mungkin sebenarnya bukan turunan satu sama lain), itu sekarang menjadi ambigu yang mana yang Anda maksud _meskipun Anda secara eksplisit menyertakan ekstensi_.

Saya berpendapat bahwa pengguna harus memberi tahu kompiler apa yang sebenarnya mereka inginkan (sebagai pengguna) dan itu adalah "mengimpor file apa pun dengan nama X dan ekstensi apa pun" (dalam kasus import ... from './foo' ) atau "impor secara khusus file ini" (dalam hal import ... from './foo.ext' ). Jika kompiler mendeteksi bahwa Anda mengimpor file TS, dan kompiler mulai mengeluarkan file .js , maka saya yakin kompiler harus memperbarui impor untuk mengimpor file yang sesuai dengan benar. Ini mungkin berarti mengubah .ts menjadi .js dalam pernyataan impor.

@justinfagnani Ada dua masalah dengan itu:

  1. Waktu proses yang mengeksekusi TS secara asli (seperti TS-Node) akan gagal berfungsi jika Anda menentukan ekstensi .js pada impor Anda.

Ini adalah bug di TS-Node. Itu tidak cocok dengan perilaku tsc .

  1. Anda berbohong kepada kompiler (IMO) jika Anda menyertakan ekstensi .js dalam impor Anda.

Sebenarnya sebaliknya - Anda mengatakan yang sebenarnya tentang apa yang sebenarnya akan diimpor. Anda _tidak_ akan mengimpor file .ts , tetapi file .js . Juga seharusnya tidak ada perbedaan yang terlihat antara pasangan .d.ts / .js dan file .ts . Mereka dapat dipertukarkan. Satu-satunya cara yang tepat untuk melakukannya adalah dengan mengimpor file .js - seperti apa file .ts setelah kompilasi.

@justinfagnani

Seharusnya tidak ada perbedaan yang terlihat antara pasangan .d.ts/.js dan file .ts

Hal ini tidak selalu benar. Anda dapat mengonfigurasi server Anda untuk melayani semua JS, TS, dan DTS dengan tipe JS MIME dan kemudian mengimpor semuanya secara terpisah dalam JavaScript dan runtime akan menjalankan semuanya sebagai JS dengan patuh. ESM tidak peduli dengan ekstensi sama sekali.

Itu sebabnya saya pikir pengguna TS harus benar-benar dipaksa untuk memasukkan ekstensi .ts dan tanpa ekstensi akan menjadi kesalahan kecuali benar-benar mengimpor file tanpa ekstensi atau nama itu. Dan TS akan menulis ulang impor menjadi .js di output. Dan jika ada file JS (bukan yang dihasilkan oleh TS) itu juga akan menjadi kesalahan.

Ini adalah bug di TS-Node. Itu tidak cocok dengan perilaku tsc.

Ini adalah batasan pemuat NodeJS, bukan bug di TS-Node: https://github.com/TypeStrong/ts-node/issues/783#issuecomment -507437929

Hal ini tidak selalu benar. Anda dapat mengonfigurasi server Anda untuk melayani semua JS, TS, dan DTS dengan tipe JS MIME dan kemudian mengimpor semuanya secara terpisah dalam JavaScript dan runtime akan menjalankan semuanya sebagai JS dengan patuh. ESM tidak peduli dengan ekstensi sama sekali.

Saya sangat menyadarinya, tetapi browser juga tidak akan menjalankan TypeScript. Hampir secara universal benar bahwa file yang sebenarnya dimuat oleh lingkungan adalah file JavaScript.

Maksud saya adalah bahwa jika Anda sudah memiliki pasangan .js / .d.ts , katakanlah dari paket pihak ke-3, dan impor file .js , tsc akan lihat file .d.ts dan muat jenisnya. yaitu, .js / .d.ts pair _acts_ seperti file .ts , dan beginilah seharusnya, karena ini adalah bagaimana Anda dapat secara transparan mem-porting dari JavaScript ke TypeScript tanpa mengubah impor file yang di-porting.

Ini adalah bug di TS-Node. Itu tidak cocok dengan perilaku tsc.

Ini adalah batasan pemuat NodeJS, bukan bug di TS-Node: TypeStrong/ts-node#783 (komentar)

Masih ada bug yang menyimpang dari TS-Node dari perilaku tsc . Itu menghasilkan file .ts yang tidak berfungsi di tsc dan TS-Node, dan saya akan sangat mempertimbangkan tsc sebagai pembuat standar yang harus diikuti oleh TS-Node .

Maksud saya adalah bahwa jika Anda sudah memiliki pasangan .js/.d.ts, katakanlah dari paket pihak ke-3, dan impor file .js, tsc akan melihat file .d.ts dan memuat jenisnya. yaitu, pasangan .js/.d.ts bertindak seperti file .ts, dan beginilah seharusnya, karena ini adalah bagaimana Anda dapat secara transparan mem-porting dari JavaScript ke TypeScript tanpa mengubah impor file yang di-porting.

Jika Anda memuat _paket_ eksternal, maka Anda memerlukan semacam pemuat paket runtime (misalnya, peta impor bernama di browser) yang melakukan pemetaan modul bernama ke file titik masuk. Namun, saya pikir poin Anda umumnya berlaku, dalam kasus di mana Anda memiliki pasangan .js/.d.ts relatif. Saya berada di pagar apakah dalam hal ini Anda harus melakukan import ... from './foo.d.ts' atau import ... from './foo.js' .

File .d.ts pada dasarnya adalah tajuk yang menjelaskan struktur yang tidak berisi informasi tentang ekstensi apa yang dipetakan (dengan asumsi bahwa umumnya Anda tidak boleh memiliki banyak file dengan nama yang sama tetapi ekstensi berbeda di tempat yang sama, dan we error pada build jika Anda melakukannya) - bahkan hari ini, "sumber" runtime yang terkait dapat berupa .js atau .jsx (menggunakan jsx: preserve ). Anda tidak dapat, secara umum, mengganti referensi .d.ts dengan .js dalam impor pada waktu emisi dan menganggapnya berfungsi ...

Sangat penting bahwa tsc tidak terlalu berpendirian tentang yang lebih luas
membangun dan menyelesaikan asumsi.

Mengingat bahwa ini adalah multi-alat pada batas yang kompleks, itu diharapkan
konfigurasi itu dapat memungkinkannya berperilaku seperti yang diinginkan pengguna.

Ada upaya yang sangat disengaja untuk tidak mengekspos perubahan resolusi sebagai
bagian dari proses kompilasi tsc - ini dengan sendirinya memaksa opini pada
pengguna dan menyebabkan gesekan dalam alur kerja mereka.

Pada Rabu, 27 November 2019 pukul 16:48 Wesley Wigham [email protected]
menulis:

File .d.ts pada dasarnya adalah header yang menjelaskan struktur yang berisi
tidak ada informasi tentang ekstensi apa yang dipetakannya (asumsinya adalah
umumnya Anda tidak boleh memiliki banyak file dengan nama yang sama tetapi
ekstensi yang berbeda di tempat yang sama) - bahkan hari ini, yang terkait
runtime "sumber" bisa berupa .js atau .jsx (menggunakan jsx: melestarikan). Anda bisa
tidak, secara umum, mengganti referensi .d.ts dengan .js dalam impor pada waktu emisi
dan anggap berhasil...


Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di GitHub
https://github.com/microsoft/TypeScript/issues/16577?email_source=notifications&email_token=AAESFSQS2DQ23RR5KN3RTZ3QV3TLXA5CNFSM4DPRQTY2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXW2ZLOKDN5WTPZ2ZLOKDN5WTPZ2ZLOKDN5
atau berhenti berlangganan
https://github.com/notifications/unsubscribe-auth/AAESFSUAP2YO23ZFHCOWVQLQV3TLXANCNFSM4DPRQTYQ
.

Tidak yakin bagaimana menangani skenario ini tetapi memiliki keraguan terkait hal yang sama.

Saya memiliki peta impor seperti ini di file html saya:

<script type="importmap-shim">
      {
        "imports": {
          "@root/":"../../../",
         }
      }
</script>

Dan saya memiliki file ts tempat saya mengimpor file seperti ini:

import '@root/components/page-main/page-main.js';

Sekarang, pengaturan ini berfungsi dengan baik di browser. Tapi, bagaimana saya bisa menavigasi/menggunakannya di VSCode? Maksud saya, saya ingin ctrl+klik pada impor dan arahkan ke file, dapatkan pelengkapan otomatis, ketik def, dll.

Juga, mengingat tsc tidak menulis ulang ekstensi impor dari .ts ke .js , apakah ada alat/paket lain yang direkomendasikan yang dapat saya gunakan untuk melakukan hal yang sama pada waktu pembuatan? Terima kasih.

(Saya menggunakan https://github.com/guybedford/es-module-shims untuk Modul ES dan mengimpor peta)

Tapi, bagaimana saya bisa menavigasi/menggunakannya di VSCode?

Cari opsi kompiler paths .

Juga, mengingat tsc tidak menulis ulang ekstensi impor dari .ts ke .js , apakah ada alat/paket lain yang direkomendasikan yang dapat saya gunakan untuk melakukan hal yang sama pada waktu pembuatan? Terima kasih.

Cukup gunakan .js dan itu akan berfungsi dengan baik, bahkan jika Anda merujuk ke file .ts pada waktu pembuatan.

@tvvignesh https://github.com/Zoltu/typescript-transformer-append-js-extension/ untuk menulis ulang impor tanpa ekstensi ke .js pada waktu kompilasi. Saya pribadi bukan penggemar "cukup masukkan .js di file TS Anda" karena kode Anda tidak akan berjalan di ts-node jika Anda melakukannya. Jika Anda tidak perlu menjalankan kode Anda di ts-node, maka menggunakan .js akan berfungsi.

Tapi, bagaimana saya bisa menavigasi/menggunakannya di VSCode?

Cari opsi kompiler paths .

Juga, mengingat tsc tidak menulis ulang ekstensi impor dari .ts ke .js , apakah ada alat/paket lain yang direkomendasikan yang dapat saya gunakan untuk melakukan hal yang sama pada waktu pembuatan? Terima kasih.

Cukup gunakan .js dan itu akan berfungsi dengan baik, bahkan jika Anda merujuk ke file .ts pada waktu pembuatan.

Terima kasih atas balasan cepat Anda. Saya telah mengatur opsi jalur di tsconfig.json tetapi masih tidak dapat menavigasi dengan ctrl+klik.

Ini adalah opsi jalur saya di tsconfig.json

"paths": {
            "*": ["www/node_modules/*"],
            "@modules/*": ["www/node_modules/*"],
            "@root/*": ["www/*"]
        }

Cukup gunakan .js dan itu akan berfungsi dengan baik, bahkan jika Anda merujuk ke file .ts pada waktu pembuatan.

Hal ini cukup tidak praktis ketika ada ribuan impor.

Masalah dengan "hanya menggunakan .js " adalah jika TypeScript mengeluarkan file .mjs maka program Anda tidak bekerja. Ini berarti Anda berakhir dalam situasi di mana Anda menulis TypeScript yang _either_ berfungsi di browser _atau_ berfungsi di NodeJS. Anda tidak lagi dapat menulis TypeScript yang berfungsi di keduanya.

Saya percaya argumen di sini adalah, "Itu bukan kesalahan TypeScript, itu adalah browser dan NodeJS yang menyimpang".

Node 13.2 mendukung ekstensi .js dengan baik.

@justinfagnani Untuk modul ES? Saya pikir NodeJS hanya akan memuat modul ES jika mereka memiliki ekstensi .mjs , jika tidak, file diperlakukan sebagai CommonJS?

Saya merasa seluruh utas ini agak salah arah. Menulis ekstensi file secara eksplisit akan menyelesaikan seluruh masalah ini. Jika Anda mengimpor file JavaScript, tulis ekstensi .js. Jika Anda mengimpor file TypeScript, tulis ekstensi .ts. Ini diperbolehkan dalam standar dan kompiler TypeScript memahami semuanya dengan baik. Satu-satunya masalah adalah bahwa kompilator menyatakan ekstensi .ts adalah kesalahan. Ini tidak mempengaruhi transpilasi murni, tetapi hanya kesalahan tipe. TypeScript harus memperbaiki ini, karena jelas ekstensi file .ts valid, karena kami menulis di TypeScript. Untuk mengatasi masalah ini, Deno.js memiliki ekstensi Kode VS: https://marketplace.visualstudio.com/items?itemName=justjavac.vscode-deno

Dengan munculnya WebAssembly, aplikasi web akan mulai mengimpor lebih banyak jenis file. Akan menjadi semakin penting untuk menyatakan secara eksplisit jika Anda mengimpor file .wasm, .js, .ts, .rs, .c, dll

Adakah yang benar-benar menggunakan skrip yang saya tulis?

https://github.com/microsoft/TypeScript/issues/16577#issuecomment -310426634

ada tanggapan jika demikian?

@QuantumInformation Saya belum pernah menggunakan skrip Anda, tetapi plugin transformator TypeScript yang saya tulis pada dasarnya melakukan hal yang sama. 😊 https://github.com/Zoltu/typescript-transformer-append-js-extension/

Pertama-tama, saya tidak akan mencoba lagi meyakinkan TypeScript untuk mengimplementasikannya, saya mengerti, Anda tidak akan melakukannya.
Saya membaca komentar dan bertanya-tanya: semua orang yang mengatakan bahwa menambahkan .js ke jalur akan menyelesaikan semuanya - apakah Anda benar-benar tidak menggunakan paket pihak ke-3? Bagaimana cara saya menambahkan ekstensi ke impor saya memperbaiki apa yang ada di node_modules?

@MicahZoltu oh bagus

Apa maksudmu? Anda akan secara eksplisit menulis ekstensi file dari file yang Anda impor dari node_modules, jika menggunakan jalur. Tapi bukankah itu hanya impor biasa?

Jika Anda menentukan jalur relatif, itu tidak akan kosong. Namun saya berbicara tentang impor internal dari paket yang saya impor, lihat rxjs misalnya.

@Draccoz Saya percaya poin yang dibuat adalah bahwa jika seseorang menulis TypeScript seperti import { ... } from './foo' dan kemudian menerbitkannya sebagai paket NPM, pengguna tidak dapat menggunakan perpustakaan itu secara langsung di browser bahkan jika itu menargetkan modul ES. Saya percaya argumen Microsoft di sini adalah bahwa paket itu salah jika mendistribusikan kode seperti itu dengan harapan itu berfungsi di browser.

Anda akan menulis ekstensi file yang ada di node_modules. import * as stuff from 'rxjs/path/to/file.js'; jika itu adalah file JavaScript, dan import * as stuff from 'rxjs/path/to/file.ts'; jika mereka mendistribusikan file TypeScript. Ini berfungsi sekarang jika saya tidak salah

@lastmjs Ya, tapi bagaimana jika rxjs/path/to/file.ts berisi import foo from './bar' ? Anda tidak dapat mengubahnya, karena Anda tidak dapat mengubah file, karena ini adalah perpustakaan pihak ketiga.

Itu sebabnya kita harus mendorong untuk menggunakan ekstensi eksplisit di mana-mana, tapi ya saya mengerti maksud Anda. Alat saya (https://github.com/lastmjs/zwitterion) melakukan penulisan ulang ini sebagai solusi stop-gap untuk file-file yang tidak memiliki ekstensi.

Ya, maksud saya persis seperti itu - hanya menambahkan ekstensi tidak akan memperbaiki perpustakaan pihak ketiga yang tidak dapat kami modifikasi, jadi itu bukan solusi.
Saya mendapatkan poin Microsoft juga, maka saya tidak mendorongnya lagi (selain fakta bahwa menjaga masalah ini tetap terbuka memberikan harapan yang tidak perlu yang menghalangi pengelola paket dari hanya menyesuaikan build alih-alih menunggu TS untuk menyelesaikan ini), itu akan menjadi luar biasa meskipun hanya memiliki TypeScript sebagai alat build dan tidak ada dependensi lainnya.

ya tapi yang jelas harapan masih baik untuk banyak orang

image

Namun, dinyatakan beberapa kali melalui komentar itu bahwa itu TIDAK akan diterapkan, jadi mengapa tetap terbuka?

jika seseorang menulis TypeScript seperti import { ... } from './foo' dan kemudian menerbitkannya sebagai paket NPM

Apakah banyak orang menerbitkan TS yang tidak dikompilasi dalam paket NPM? Saya melihat ini untuk penggunaan internal saya sendiri. Saya membuat perpustakaan kode umum yang dibagikan di antara proyek dan menganggap NPM adalah cara yang masuk akal untuk mengemasnya, dan tim kami telah pindah ke TS secara eksklusif jadi saya akan senang untuk menghindari kompilasi deps. Tapi sepertinya kasus penggunaan yang paling umum adalah membangun paket ke JS dengan pengetikan terpisah, lalu arahkan modules atau main ke JS dan types ke pengetikan.

Apakah ada konvensi untuk menerbitkan TS yang tidak dikompilasi ke NPM? Jika demikian, apakah ini didokumentasikan di suatu tempat? Saya mengerti bahwa ini menyimpang dari masalah aslinya, tetapi saya pikir ini relevan dengan jawabannya, karena kita perlu tahu apakah "TypeScript pihak ketiga" (paket) adalah kasus/tujuan penggunaan yang didukung.

@thw0rted Maaf karena tidak jelas, maksud saya:

...jika seseorang menulis TypeScript seperti import { ... } from './foo' dan kemudian mentranspilasikannya ke JS menggunakan TSC hari ini dan menerbitkan JS itu sebagai paket NPM...

Jika TIDAK akan diimplementasikan, saya akan menyerahkannya kepada MS untuk menutup masalah sekarang.

Ah, aku mengerti sekarang. Ya, ketika saya mentranspile (dengan target: ES2018 ) JS yang dipancarkan meninggalkan ekstensi dari pernyataan impor, tetapi itu berfungsi untuk saya karena konsumen meletakkan semuanya melalui webpack/babel dan itu harus mengisi ekstensi yang hilang untuk saya. Aku sampai dengan kecepatan sekarang. Bahkan tidak terpikir oleh saya bahwa "paket" saya tidak akan berfungsi secara asli di browser tanpa melakukan perjalanan melalui webpack terlebih dahulu.

Ya, ini yang sulit.

@thw0rted Saya tidak menggunakan webpack/babel, oleh karena itu menyelesaikan .js dari kotak adalah masalah bagi saya.
Beberapa solusi/solusi adalah mengonfigurasi server web untuk sumber penyelesaian default .

Maaf jika saya mengulangi apa yang dikatakan orang lain, tetapi ini adalah sesuatu yang saya tangani setiap hari, jadi saya ingin memasukkan dua sen saya yang tidak diminta.

Saya tahu bahwa TypeScript tidak harus memenuhi lingkungan tertentu (Node.js, Webpack, dll.) tetapi kenyataannya adalah bahwa ada banyak lingkungan di mana ekstensi selalu diperlukan, kecuali jika dikonfigurasi secara khusus, jadi saya tidak melakukannya. t berpikir mereka harus diabaikan. Impor tidak lagi berada di belakang bendera di Node dan jalur impor harus cocok dengan nama jalur URL di web. Meskipun tidak ada kebutuhan teknis untuk memiliki .js di akhir URL, itu adalah standar de facto.

Jika orang-orang baik di Microsoft benar-benar ingin tidak memiliki ekstensi file sebagai default, saya tidak akan berdebat tentang itu. Anda mungkin lebih pintar dari saya, tetapi saya pasti akan lebih bahagia jika alih-alih menyimpulkan apakah ekstensi diperlukan atau tidak berdasarkan impor lain dalam file yang sama, yang dapat diatur di seluruh proyek sehingga akan berfungsi untuk pelengkapan otomatis Intellisense untuk yang pertama impor ditambahkan ke file!

Sementara itu, apakah ada yang tahu plugin VSCode yang memperbaiki ini? Menambahkan impor/ekstensi ke eslint adalah yang terbaik yang bisa saya lakukan untuk menangani ini.

Saat ini saya menulis baris import tanpa ekstensi .js, dan kemudian menggunakan sed untuk menambahkan ekstensi .js dalam file keluaran.
https://github.com/yoursunny/NDNTs/blob/9f50fcec245b33c7649fa815bbb3dd404eee160e/mk/build.sh#L12 -L14
Saya harus menghapus SourceMaps selama pembuatan produksi, karena mereka tidak lagi cocok setelah file keluaran dimodifikasi.

Saya tidak dapat menulis ekstensi .js di file sumber .ts karena merusak ts-jest .
Meskipun dimungkinkan untuk menjalankan Jest pada file .js yang dikompilasi, itu merusak Coveralls .

@yoursunny Ya, sed adalah varian (saya juga menggunakannya tetapi lebih suka replace-in-file karena konfigurasi yang dapat dikonfigurasi dengan pemetaan file importmap) untuk mengganti string dalam file js yang dihasilkan, tetapi baunya tidak enak =) Mungkin menambahkan ekstensi akan menjadi fitur/opsi yang berguna untuk ttypescript dengan plugin transformasi (mis. Typescript-transform-paths oleh @MicahZoltu).

@richardkazuomiller bagian ini tidak benar:

Jika orang-orang baik di Microsoft benar-benar ingin tidak memiliki ekstensi file, jadilah default

TypeScript saja:

  1. Mengizinkan resolusi modul gaya-Node-require (mereka harus memperluas ini untuk memungkinkan resolusi gaya-Node-impor, yang memerlukan ekstensi file).
  2. Di unit kompilasi yang sama, menyelesaikan file .js menjadi pasangan .js/.d.ts bahkan sebelum file tersebut dibuat oleh kompiler.
  3. Tidak mengubah penentu impor _sama sekali, selamanya_.

Jadi solusi untuk semua ini adalah dengan mengimpor file .js dengan ekstensi .js . TypeScript akan menyelesaikan ke file .ts yang tepat dan tidak mengubah penentu impor, jadi semuanya hanya akan berfungsi di browser dan Node >= 13.2.

@yoursunny apakah Anda mengajukan bug terhadap ts-jest ? Mereka menyimpang dari standar TypeScript de facto di sini. Juga tampak seperti bug di Coverall jika tidak dapat menggunakan peta sumber pada file .js.

apakah Anda mengajukan bug terhadap ts-jest ? Mereka menyimpang dari standar TypeScript de facto di sini.

Tidak, karena saya tidak sepenuhnya mengerti cara kerja resolusi ts-jest.

Juga tampak seperti bug di Coverall jika tidak dapat menggunakan peta sumber pada file .js.

Coverall menerima laporan lcov dari proses build saya, dan kemudian menampilkan cakupan kode menggunakan file yang dikomit ke GitHub.
Saya tidak mengkomit file .js keluaran ke GitHub. Jika saya menjalankan pengujian unit pada file .js, laporan lcov akan merujuk file .js yang tidak ada di GitHub.
Oleh karena itu, Coverall tidak dapat menemukan file sumber. Ini akan menampilkan persentase cakupan, tetapi tidak dapat menunjukkan garis mana yang tidak tercakup.

Era baru telah tiba!

Node.js v13 yang baru dirilis dan semua browser utama mendukung Modul ES asli di luar kotak, dan TypeScript akan sangat bagus untuk mendukung lingkungan ini dengan cara yang sederhana.

Solusi paling sederhana untuk kasus penggunaan paling dasar (situs web yang disajikan melalui server file statis sederhana) adalah dengan menambahkan opsi kompiler baru seperti "appendJsExtension": true atau yang serupa.

@mjbvz Masalah dalam repo Kode VS yang Anda tutup sedikit berbeda: ini tentang menggunakan pelengkapan otomatis untuk menambahkan pernyataan impor secara otomatis; ketika VS Code melakukan ini adalah menambahkan pernyataan impor tanpa ekstensi .js , dan mudah untuk mengabaikan ini sampai runtime gagal.

Namun jika TypeScript menambahkan opsi seperti "appendJsExtension": true atau yang serupa, maka itu tidak masalah, dan kita dapat menulis kode TS tanpa .js di sumbernya.

Mungkin plugin VS Code, harus memiliki opsi untuk mengaktifkan/menonaktifkan penambahan otomatis ekstensi .js dalam pernyataan impor yang dilengkapi secara otomatis?

@mjbvz Masalah Kode VS / Intellisense terkait, tetapi tidak boleh ditutup sebagai penipuan. Jika masalah ini akhirnya ditutup sebagai WONTFIX, itu sebenarnya akan meningkatkan pentingnya masalah Kode VS.

Saya melihat satu poin diabaikan dan tidak memahami bagaimana solusi di mana ekstensi JS adalah kasus khusus akan menyelesaikan ini: untuk ESM, tidak ada ekstensi yang memiliki status khusus, bahkan file tanpa ekstensi sepenuhnya baik-baik saja selama server menyajikannya ke browser dengan jenis MIME teks/javascript yang sesuai. Itu berarti kode itu seperti:

import something from './javascript-code.png';
import something2 from './javascript-code2.js';
import something3 from './javascript-code3.ts';

Ini semua valid selama file (terlepas dari ekstensinya) berisi kode JavaScript dan disajikan ke browser dengan jenis JavaScript MIME.

Karena TypeScript harus menjadi superset JavaScript yang aman untuk tipe, saya tidak melihat cara untuk mengizinkan impor seperti yang di atas, karena kodenya adalah JavaScript yang valid dan jika TypeScript tidak menerimanya, itu tidak lagi menjadi superset yang aman dari JavaScript, bukankah itu benar?

Jadi solusi di mana ekstensi JS tersirat atau satu-satunya yang diizinkan menurut saya tidak dapat memotong ini? Selain itu, bahkan ekstensi TS dan DTS IMO tidak dapat diberi casing khusus, karena meskipun hal ini biasanya tidak terjadi, mereka dapat berisi kode JavaScript, bukan kode TypeScript dan server ke browser tanpa masalah sama sekali sejauh menyangkut ESM. , mengingat mereka disajikan dengan tipe MIME yang tepat.

Apakah saya kehilangan sesuatu di depan ini? Mungkinkah TypeScript tidak menerapkan dukungan untuk ekstensi arbitrer (termasuk yang hilang) dalam impor kode, dan apakah mungkin bagi TypeScript untuk terus mengasumsikan ekstensi TS dalam impor modul, mengingat file.ts dan file (tidak ada perpanjangan) kemudian akan mengakibatkan konflik?

Pekerja Web dan Layanan juga mendapatkan dukungan untuk impor/ekspor Modul ES .

Saya sepenuhnya mendukung dan mendukung ide @trusktr untuk mengimplementasikan ide mereka sebagai opsi kompiler. Bukannya saya ingin menyingkirkan bundler seperti webpack dan rollup. Tapi saya yakin fitur seperti ini akan menghilangkan banyak kerumitan dan waktu yang dihabiskan untuk menyiapkan bundler, ketika semua yang Anda inginkan adalah mengkompilasi proyek TypeScript sederhana tanpa melompat melalui rintangan atau menggunakan solusi yang canggung.

Harap pertimbangkan ini sebagai opsi untuk kompiler TypeScript. <3

Adakah yang tahu cara menjalankan file js individual yang dikompilasi di browser tanpa webpack atau --outFile , menggunakan sistem modul apa pun?

Masalah saya adalah ini: proyek TypeScript yang cukup besar yang saya kerjakan membutuhkan waktu sekitar 35 detik untuk dikompilasi dengan webpack menjadi file js yang dibundel menggunakan ts-loader .
Satu-satunya cara saya dapat mengoptimalkan ini adalah menggunakan transpileOnly yang memotong waktu kompilasi menjadi 20 detik tetapi itu masih lambat dan saya kehilangan pengecekan tipe.
Menyingkirkan webpack Saya bisa mendapatkan sekitar 14 detik menggunakan outFile tapi itu masih terlalu lambat untuk saya. Menggunakan incremental tidak ada bedanya.

Satu-satunya cara saya bisa mendapatkan beberapa detik waktu kompilasi adalah dengan memancarkan 1 file js per 1 file ts, dan menggunakan flag incremental . Dalam hal ini saya membayangkan ts hanya mendeteksi dan mengkompilasi file yang benar-benar telah berubah. Masalahnya adalah saya tidak bisa menjalankan ini di browser di salah satu target modul yang saya coba: system, amd, es6.
Saya menggunakan pemetaan paths di tsconfig.json dan dalam file js yang dikompilasi, kesalahan yang saya dapatkan sebagian besar terkait dengan tidak dapat menyelesaikan alias tersebut.

Apakah ada cara untuk mencapai hal ini?

@andrewvarga Saat ini saya menjalankan semua TypeScript yang dikompilasi langsung di browser tanpa bundling atau kompilasi ke satu file. Cara termudah untuk melakukannya adalah:

  1. Pastikan semua impor dalam file TypeScript memiliki ekstensi .js .
  2. Jalankan server dev yang menyelesaikan impor nama paket npm untuk dependensi, jika perlu. es-dev-server adalah yang paling sederhana yang saya tahu.
  3. Jalankan tsc --watch (pastikan modul esnext di tsconfig Anda)

Itu dia. Jika Anda hanya menulis ekstensi .js untuk impor di TypeScript Anda, Anda tidak memerlukan alat lain untuk memperbaiki file untuk browser.

@justinfagnani mate, Anda lupa informasi terpenting - tipe harus dalam format jsdoc, abstraksi TypeScript apa pun di atas JavaScript asli akan membuat parser gagal.

@Draccoz tsc akan menampilkan JavaScript, bukan TypeScript.

@andrewvarga Cara paling sederhana yang saya tahu untuk transpile tanpa bundling adalah proyek saya Zwitterion . Ini dirancang untuk menjadi pengganti server file statis, sehingga Anda tidak perlu mengubah cara Anda mengembangkannya. Anda dapat mengimpor dan mengekspor dengan ekstensi file eksplisit (.js untuk JavaScript dan .ts untuk TypeScript), bahkan dalam elemen skrip. Ini sangat berkinerja, melakukan caching dan memuat ulang otomatis ketika file berubah. Anda harus mengandalkan editor Anda untuk analisis statis (kesalahan ketik)

@andrewvarga Saya menggunakan https://github.com/Zoltu/typescript-transformer-append-js-extension/ dan menargetkan modul ES asli yang dimuat di semua browser modern (kecuali Safari, IE baru).

Jika dependensi NPM runtime Anda sangat terbatas, Anda dapat memuatnya dengan es-modules-shim tanpa bundling apa pun. Anda dapat melihat templat reaksi yang saya buat yang menunjukkan semua ini bekerja bersama: https://github.com/Zoltu/react-es2015-template

@MicahZoltu Safari memang memiliki dukungan modul ES, saya tahu faktanya, berdasarkan caniuse dan pengalaman pribadi: https://caniuse.com/#search =modules

@justinfagnani awww maaf, melewatkan bagian "TypeScript yang dikompilasi", mengira Anda berbicara tentang TypeScript jsdoc.

Terima kasih semua atas berbagai tipnya!

Apa yang saya temukan adalah bahwa dengan menggunakan modul hard-source-webpack-plugin npm untuk webpack dan transpileOnly: true dalam opsi ts-loader memangkas waktu pembuatan menjadi sekitar 4-5 detik.
Ini tentu saja akan mengabaikan kesalahan TypeScript, jadi ini hanya berguna untuk iterasi cepat dalam membangun, mencoba di browser, dan mengandalkan IDE untuk kemungkinan kesalahan apa pun, tetapi saya pikir ini sangat berguna selama pengembangan.

Untuk mendapatkan kesalahan TS dan kompilasi cepat, saya masih berpikir satu-satunya cara adalah menjalankan modul di browser tetapi kurangnya dukungan untuk import-maps dan ekstensi js membuatnya sulit.
@justinfagnani @MicahZoltu terima kasih, saya akan mencoba opsi itu. Secara umum saya lebih suka menghindari menggunakan satu modul npm lagi tetapi tampaknya itu tak terhindarkan.

Saya mencoba membuatnya bekerja menggunakan systemjs juga, tetapi saya terjebak dengan peta impor..

@andrewvarga Anda dapat mencoba SystemJs dengan contoh ringan saya dengan importmap.
Anda juga dapat mencoba contoh berat saya - alternatif systemjs & esm, tetapi esm importmaps tidak didukung oleh native, dan kita harus menyelesaikan modul secara manual (gulp-replace), atau Anda dapat mencoba es-module-shims .

Jadi jika saya menggunakan tsc sebagai satu-satunya kompiler saya, menargetkan esnext atau es2015 sebagai tipe modul saya. Apakah ada cara saya dapat menggunakan output langsung di browser saya?

https://github.com/alshdavid-sandbox/typescript-only-compiler

Jika saya memahami sisa utas ini dengan benar, TypeScript akan dengan senang hati mengkompilasi kode Anda jika Anda mengubah baris ini menjadi from "./module.js" . Kemudian index.js yang dikompilasi akan memiliki pernyataan impor ES6 yang valid dan semuanya akan berfungsi.

Itu kecuali Anda mengimpor beberapa perpustakaan yang tidak tahu cara ES Import atau tidak peduli :P.

Saya membuat plugin untuk Gulp yang menambahkan .js untuk mengimpor jalur file. (juga resolusi jalur bonus ts).

Saya menggunakan Gulp karena saya tidak tahu ada pelari tugas lain yang memungkinkan saya untuk melampirkan langkah pasca-pemrosesan sederhana ke kompiler tsc (baik jam tangan dan mode normal). Webpack dan rollup keduanya bundel secara eksklusif, dan saya ingin memancarkan modul es.

Ini berfungsi tetapi lambat untuk ditonton karena tampaknya membangun kembali semuanya.

https://github.com/alshdavid-sandbox/typescript-only-compiler/tree/gulp

Ini semakin penting karena tim simpul memutuskan untuk tidak mengimpor tanpa ekstensi
https://github.com/nodejs/modules/issues/444

Tambahkan peta impor juga memutuskan impor tanpa ekstensi
https://github.com/WICG/import-maps/issues/194

Jika kita ingin menggunakan modul es yang dikompilasi TypeScript di browser atau node, kita perlu memiliki ekstensi yang ditambahkan oleh TypeScript? (untuk modul internal) dan secara manual untuk modul eksternal? @weswigham

@chyzwar lagi, jika Anda cukup menulis ekstensi .js di sumber TypeScript Anda, maka output yang dikompilasi akan memiliki ekstensi yang benar dan modul akan berfungsi di browser dan Node.js. Anda tidak memerlukan alat transformasi tambahan atau tsc untuk melakukan apa pun untuk Anda.

Lebih mudah bagi pengembang untuk melakukan hal berikut: Jika itu adalah file sumber TypeScript, tulis ekstensi .ts. Jika ini adalah file sumber JavaScript, tulis ekstensi .js. Itu juga akan dikompilasi dan dijalankan dengan benar di browser (.ts akan membutuhkan tipe MIME aplikasi/javascript). Ekstensi harus cocok dengan jenis file sumber. Modul tsc dan ES dapat mengatasinya (setidaknya modul ES di browser, semoga Node.js mengikuti hal yang sama)

@justinfagnani tsc cukup senang dengan ini, dan adil untuk mengatakan "bukan masalah kita" di sini tetapi tampaknya tidak ada konsensus di sini tentang apa yang benar,

Antara tsc, vscode, webpack, dan ts-node tidak ada yang benar-benar setuju dengan standar yang baru saja tersedia secara native (sekarang tersedia browser dan node).

Contoh 1

Saya ingin menulis paket javascript modern, menulisnya dalam TypeScript dan menghapus jenisnya untuk distribusi sebagai modul ecmascript (mempertahankan pernyataan impor dan ekspor).

Contoh 2

Saya sedang membangun situs web statis menggunakan modul di vscode, secara default akan otomatis mengimpor tanpa ekstensi untuk setiap impor pertama dan Anda perlu menyesuaikan ini secara manual.

Dalam kasus ini, tsc dapat menangani ini, dan bahkan mengekspor file deskriptor yang mendukung kemudian menggunakan distribusi modul es dari TypeScript dengan pengetikan penuh (luar biasa).

Tetapi jika saya ingin menjalankan kode pengujian terhadap sumbernya, saya bisa menggunakan ts-node tetapi di sini ts-node tidak senang.

Demikian pula, fakta bahwa tsc, vscode, dan webpack telah berevolusi untuk melakukan hal berikut:

  1. impor otomatis vscode tanpa ekstensi
  2. tsc akan dengan senang hati menulis ulang impor ke file js yang berarti file ts
  3. webpack melakukan berbagai keajaiban di sini untuk mencari ekstensi default

Apakah semua hal yang harus dipertanyakan sekarang karena empat implementasi (chrome, firefox, safari, node) semuanya berharap bahwa jalur impor harus mengarah ke sesuatu yang dapat diselesaikan langsung ke file.

Menambahkan .js ke impor seharusnya merupakan solusi sementara, bukan solusi yang pasti. Jika ada, rasanya seperti diretas. Cara untuk menipu kompiler. Dan mencoba mengakali kompiler adalah ideologi yang mengerikan untuk diikuti. Saya hanya bisa membayangkan betapa membingungkannya hal ini bagi orang-orang yang baru mengenal TypeScript. Bahasa yang seharusnya membantu pengembang Javascript menulis kode _lebih baik_.

Seperti yang sudah disebutkan sejumlah orang, jika Anda menambahkan .js ke impor, TypeScript akan menampilkannya dan semuanya berfungsi (setidaknya dalam kode Anda). Alasan bahwa tsc harus menambahkan ekstensi karena tidak berfungsi di browser seperti meminta TypeScript untuk memperbaiki kesalahan runtime yang disebabkan oleh pengembang - ok tapi mengapa pengembang tidak dapat memperbaikinya sendiri?
Jangan salah paham, saya ingin tsc menjadi satu-satunya ketergantungan pengembang saya, tetapi beberapa hal tidak akan terjadi dan akan tetap seperti mimpi.

Saya ingin tsc menjadi satu-satunya ketergantungan dev saya, tetapi beberapa hal tidak akan terjadi dan akan tetap seperti mimpi.

Saya pasti telah melihat lusinan komentar yang hampir identik selama beberapa tahun di #3469, termasuk beberapa dari tim TypeScript. "Ini adalah pemeriksa tipe, itu seharusnya melakukan satu hal dengan baik, jangan berharap itu menggantikan seluruh rantai alat Anda ..." Butuh 3 tahun, tetapi mereka masih menambahkan mode pembuatan, karena kasus yang bagus dibuat bahwa itu adalah arah yang benar untuk pergi.

Webpack dan rollup keduanya bundel secara eksklusif, dan saya ingin memancarkan modul es.

@alshdavid Rollup dapat bekerja untuk Anda jika Anda mengatur format output ke esm dan mengatur preserveModules ke true : https://rollupjs.org/guide/en/#preservemodules

mungkin impor "tanpa ekstensi" adalah dosa asal, tidak kompatibel dengan cara kerja browser

sekarang saatnya untuk memperbaiki kode sumber kami dan menyertakan ekstensi .js : kami menemukan ketika Anda menambahkan ekstensi .js ke kode sumber Anda hari ini, semuanya berfungsi: browser puas, TypeScript agnostik, dan para bundler tidak peduli

jadi mungkin tanpa ekstensi adalah cacat dalam kode sumber kami yang dikompensasi oleh alat lama kami

Menulis ekstensi .js dalam impor dalam kode sumber TypeScript adalah omong kosong. Ini berfungsi, mempertahankan ekstensi dalam output, tetapi mungkin akan gagal dengan kesalahan "tidak dapat menyelesaikan file" dalam aturan ESLint (atau TypeScript) di VSCode atau editor apa pun yang Anda gunakan. Belum lagi saat Anda menguji kode sumber TypeScript itu. Maka alat pengujian juga harus tahu tentang perilaku omong kosong itu. Saya hampir yakin itu akan menimbulkan kesalahan yang tidak dapat menyelesaikan file.

Contoh dasar

src/index.ts
src/foo.ts
test/index.ts

src/foo.ts

export default (a: number) => a + 100;

src/index.ts

// okay, editor (without ESLint) doesn't report error here
import foo from './foo.js';

export default () => {
  console.log(foo(123));
}

tes/index.ts

// errm... ts or js ext?! .ts should be the one that make sense
// and that's how the testing too will expect it to be, otherwise will throw
// but then it will detect some weird `.js` ext in the source files...
// which again won't be able to resolve... complete bullshit. 
import main from '../src/index.ts';
import foo from '../src/foo.ts';

test('some boolshit', () => {
  main();
});

test('about foo', () => {
  foo(20);
});

Maaf untuk penggunaan "omong kosong", tapi itulah kenyataannya.

Saya tidak berpikir itu sulit untuk mengimplementasikan opsi dasar ketika kompiler melihat ekstensi ( .ts ) dalam impor untuk mengubahnya menjadi .js (atau bahkan secara opsional mengizinkan menentukan apa output ext ke menjadi). Ketika tidak ada ekstensi, jangan pertahankan ekstensi (perilaku semi-saat ini?).

Menulis ekstensi .js dalam impor dalam kode sumber TypeScript adalah omong kosong. Ini berfungsi, mempertahankan ekstensi dalam output, tetapi mungkin akan gagal dengan kesalahan "tidak dapat menyelesaikan file" dalam aturan ESLint (atau TypeScript) di VSCode atau editor apa pun yang Anda gunakan.

Ini tidak benar. ESLint, TypeScript, VS Code, dan setiap alat terkait TypeScript lainnya yang saya gunakan _just work_ dengan metode ini. Ini bukan peretasan, dan memiliki alasan yang sangat masuk akal di sekitarnya: bahwa file yang Anda impor sebenarnya _is_ file .js , dan ekstensi Anda tidak boleh berubah hanya karena file yang diimpor adalah bagian dari lokal proyek, atau dikompilasi sebelumnya sebagai bagian dari paket pihak ketiga.

Sekali lagi, saya menulis semua kode TypeScript saya dengan cara ini dan itu menyelesaikan semua masalah yang diangkat di utas ini. Outputnya berfungsi dengan baik di browser dan Node.js. Ini bukan omong kosong, itu hanya bekerja, _today_.

Tidak. Setidaknya dalam kasus yang paling umum di mana direktori keluaran adalah dist atau build atau lib dan lain-lain. File yang dikompilasi tidak berada di direktori yang sama, mereka tidak pernah ada there (dalam src/ ) - baik selama pengujian, maupun selama pengkodean di editor.

Memiliki/melihat dan mengimpor ./foo.js di src/index.ts di atas tidak masuk akal bagi saya - kecuali tentu saja jika Anda benar-benar bermaksud mengimpor file js/json, yang sepenuhnya tidak masalah. Tetapi untuk menulis ./foo.js ketika yang Anda maksud adalah file sumber TypeScript lain ( ./foo.ts ) adalah... brutal. Ini menyesatkan dan membingungkan, dan pasti salah.

Saya hampir yakin jika saya menjalankan test/index.ts di atas dengan Jest itu akan gagal dengan kesalahan yang tidak dapat ditemukan/dipecahkan ./foo.js karena hanya ada ./foo.ts .

Jika kita kesampingkan semuanya, mengapa ekstensi .js diperbolehkan tetapi tidak .ts satu (ts report error di editor)? Ini inkonsistensi dasar, sederhana dan bodoh. Seperti banyak masalah "hanya karena" lainnya di TypeScript.

Saya benar-benar kehilangan logika mengapa masalah ini dinamai seperti itu padahal sebenarnya mungkin untuk diakhiri dengan ekstensi .js . Saya pikir masalahnya adalah kebalikannya - tidak dapat diakhiri dengan .ts (mulai 3.7+)

mengapa ekstensi .ts dalam impor dilarang total?!

Dan mari kita klarifikasi. Saya berbicara tentang waktu dan pengalaman pengembangan. Saya mengerti mengapa kita dapat mempertahankan ekstensi .js dalam output yang dikompilasi, dan mengapa kita dapat menambahkan .js ext ke impor dalam file .ts tanpa melaporkan kesalahan, dan saya aku baik-baik saja dengan itu.

TypeScript adalah superset dari JavaScript tetapi bukan JavaScript. JavaScript adalah target kompilasi untuk TypeScript.

Dengan mengingat hal itu, terlepas dari pengetahuan bahwa TS akan dikompilasi ke JS, saya berharap kode TypeScript berperilaku di manor yang sepenuhnya mandiri.

Menulis .js ketika mencoba mengimpor file .ts mengasumsikan pengetahuan tentang jenis kompilasi target dan mengasumsikan bahwa target kompilasi selalu JavaScript.

Bagaimana jika kita mengkompilasi TypeScript ke biner perakitan web atau menjalankan kode TypeScript menggunakan runtime alternatif seperti Deno atau ts-node.

Pernyataan impor yang diakhiri dengan .js tidak masuk akal dalam konteks seperti itu.

Saya lebih suka dipaksa mengetikkan .ts di jalur impor saya atau tidak memiliki ekstensi tertentu yang menganggap file sumber TypeScript.

Sangat menyedihkan bahwa TypeScript menemukan ekstensinya sendiri alih-alih hanya gula sintaksis seperti aliran.

@phaux Saya tidak akan pernah ingin bekerja dengan proyek, yang mencampur file sumber dan dist di bawah ekstensi yang sama, bahkan jika mereka tinggal di folder yang berbeda. Ini seperti memberi nama semua file hanya index.js karena mereka tinggal di folder yang berbeda...

Masalah ini (yang lebih besar dari TypeScript) tampaknya memblokir IntelliSense Visual Studio Code agar tidak berfungsi di browser web dan Node -- yang memerlukan jalur file (relatif) lengkap dalam penentu impor. Tanpa ini, pernyataan import yang dihasilkan hanya berfungsi dengan transpiler dan bundler, seperti WebPack dan TypeScript itu sendiri.

Tanggapan tim VSCode adalah bahwa ekstensi harus ditambahkan oleh kode yang memberikan saran impor otomatis. Saya menduga itu adalah Server Bahasa TypeScript (bukan tsc , yang telah dibahas di sini).

Dapatkah seseorang yang benar-benar mengetahui banyak hal mengonfirmasi (atau mengoreksi) bahwa VSCode mendapat saran impor otomatis dari Server Bahasa TypeScript?

situasinya sedikit rumit dan bernuansa, jadi sementara ekstensi ".js" awalnya bertentangan dengan intuisi dan cita-cita elegan banyak orang, mungkin tidak bijaksana dan membingungkan jika TypeScript menyimpang jauh dari standar browser yang diratifikasi dan implementasi yang dikirimkan

jadi mungkin kita mempertimbangkan paradigma saat ini sebagai berikut:
impor TypeScript menjelaskan apa yang diimpor saat runtime – yaitu, impor Anda dijalankan di direktori "dist" Anda, bukan "src" – seperti panggilan fetch dan lainnya – jika kami dapat mentolerir ide ini, sisanya menjadi sederhana dan konsisten

sepertinya ide yang buruk untuk memiliki TypeScript secara membabi buta melampirkan ".js" ke impor tanpa ekstensi seperti yang dilakukan node untuk commonjs (perlu dicatat bahwa dukungan node esm memerlukan ".js" dengan cara yang sama seperti TypeScript hari ini) – melampirkan ".js" secara membabi buta akan membuat masalah baru, seperti mengimpor file javascript yang benar-benar tanpa ekstensi, atau bahkan jenis file lain seperti css atau json – ini akan membuat ekstensi bermakna dan memerlukan logika penguraian khusus, menciptakan perbedaan mencolok antara semantik browser dan TypeScript – dan kami jelas tidak akan melakukannya untuk menulis ulang panggilan fetch dengan cara yang sama, jadi mungkin import harus tetap serupa?

namun, saya bertanya-tanya – apakah relatif tidak berbahaya bagi TypeScript untuk mengonversi ekstensi ".ts" menjadi ".js"?

tentu saja, itu akan membuat tidak mungkin mengimpor file javascript yang memiliki ekstensi ".ts" – tapi mungkin itu sedikit sihir funky yang bisa kita toleransi? di sisi lain, ini adalah perbedaan idiosinkratik magis yang funky antara browser dan semantik TypeScript yang harus dipelajari dan dipahami oleh pengembang (pasti menciptakan gotchya yang aneh) - jadi naluri saya adalah meninggalkan hal-hal di tempat mereka berdiri hari ini

di sisi lain, jika kita menjaga semuanya apa adanya, keajaiban hanya dipindahkan ke TypeScript, yang harus menghubungkan impor ".js" ke file sumber ".ts" yang sesuai – ini menurut saya seperti lokasi yang lebih masuk akal untuk menyimpan keajaiban, menjadi internal untuk TypeScript alih-alih menginjak-injak semantik browser

mengejar

@rconnamacher , @TomasHubelbauer

Masalah ini (yang lebih besar dari TypeScript) tampaknya memblokir IntelliSense Visual Studio Code agar tidak berfungsi di browser web dan Node -- yang memerlukan jalur file (relatif) lengkap dalam penentu impor. Tanpa ini, pernyataan impor yang dihasilkan hanya berfungsi dengan transpiler dan bundler, seperti WebPack dan TypeScript itu sendiri.

saya pikir hanya ada beberapa kebingungan di sini – hari ini sangat mungkin untuk membuat perpustakaan atau aplikasi TypeScript yang bekerja sangat baik dengan vscode dan intellisense, yang bekerja di browser dan node, dan bekerja di esm atau commonjs – solusi yang benar-benar universal dimungkinkan hari ini

saya telah mengerjakan beberapa perpustakaan terbuka yang menunjukkan ini – renraku , sinis , redcrypto , otoriter

kirimi saya email dan saya akan dengan senang hati menjelaskan lebih lanjut

:gelombang: mengejar

Poin lainnya adalah hal itu menyebabkan kebingungan dalam file apa yang Anda akses. Sudah ada ambiguitas tentang apa yang tsc terlihat setelah resolusi modul ketika Anda memiliki file .js dan .ts secara berdampingan.

/folder
  a.ts
  a.js
  index.ts

Jika di index.ts , saat menggunakan moduleResolution: 'node'

// points to a.ts
import * as a from './a` 

// points to a.ts
import * as a from './a.js` 

// compiler emits error
import * as a from './a.ts` 

Sudah ada ambiguitas tentang apa yang dilihat tsc setelah resolusi modul ketika Anda memiliki file .js dan .ts secara berdampingan.

Oke, tentu, semacam itu, tetapi jika a.js tidak lain adalah versi a.ts yang ditranspilasikan, maka ada sesuatu yang salah dan itu bukan kesalahan TypeScript.

@thw0rted jika Anda mengkompilasi ke satu file bundel JS, TypeScript tidak akan menghasilkan rekanan JS untuk file TypeScript input, hanya file bundel tunggal. Dalam hal ini, adalah sah untuk memiliki file JS dan file TS dengan nama yang sama yang tidak sesuai dengan cara apa pun.

Ini bukan "ilegal" tapi itu tidak berarti itu ide yang bagus. Apakah Anda memiliki contoh nyata di mana Anda sebenarnya menginginkan ini?

Akan lebih baik menggunakan TypeScript tanpa bundler, loader dan dengan cara yang memancarkan JavaScript yang dapat digunakan langsung oleh browser modern.

Sebagai contoh:
https://github.com/alshdavid/tsc-website

Tapi saya merasakan sakitnya masalah ini. Tim TypeScript tidak ingin menerapkan resolusi modul. Ini adalah alasan yang sama mengapa kompiler TypeScript tidak dapat mengonversi paths ke jalur relatif aktualnya pada waktu kompilasi.

Mengonversi impor dari .ts menjadi .js , atau menambahkan .js ke impor tanpa ekstensi berarti tim TypeScript akan mengimplementasikan resolusi modul dan itu di luar cakupan.

Solusi untuk ini adalah tim TypeScript menyediakan cara untuk memperkenalkan ekstensi sehingga kami dapat mengimplementasikan hal-hal ini.

Solusi untuk ini adalah tim TypeScript menyediakan cara untuk memperkenalkan ekstensi sehingga kami dapat mengimplementasikan hal-hal ini.

Mereka melakukannya, hanya saja tidak diekspos melalui tsc (hanya melalui doa terprogram dari kompiler). Untungnya, seseorang membuat pembungkus di sekitar kompiler inti yang berfungsi _ persis_ seperti tsc kecuali mendukung ekstensi melalui konfigurasi. Dengan menggunakan pembungkus tsc ini, Anda dapat menggunakan ekstensi seperti https://github.com/Zoltu/typescript-transformer-append-js-extension/ untuk menambahkan ekstensi .js secara otomatis.

@alshdavid contoh Anda di GitHub berfungsi di browser tanpa bundler jika Anda hanya menyertakan ekstensi .js pada impor. Saya mengajukan PR untuk memperbaikinya.

@alshdavid Mungkin Anda menarik dalam proyek sampel saya (esm untuk modern & IE11 dengan SystemJS ).
Tapi saya terpaksa menyelesaikan modul esm secara manual =(

Saya tidak punya masalah pada prinsipnya dengan menempatkan .js di semua import saya, tetapi sayangnya itu memperlihatkan interaksi yang buruk dengan beberapa alat. Misalnya, ts-node tersedak: https://github.com/TypeStrong/ts-node/issues/783. Tampaknya tidak ada kesepakatan yang jelas tentang tanggung jawab siapa ini - TypeScript untuk memancarkan ekstensi .js (dalam beberapa keadaan) atau setiap alat yang menggunakan sumber TypeScript untuk melakukan terjemahan. Dan selama semua orang mau membayar, pengguna menderita dengan plugin yang tidak terdokumentasi dengan baik atau pekerja layanan yang canggung untuk mengatasi ketidakcocokan interop.

Apakah ada pembaruan tentang ini? Sejujurnya saya tidak percaya bahwa sepertinya tidak mungkin menggunakan TypeScript secara normal hari ini tanpa pemuat atau bundler modul eksternal seperti Webpack. Ini tampak sangat aneh dan juga membuat saya frustrasi. Jika saya harus menggunakan beberapa modul eksternal untuk membuat TypeScript berfungsi sepenuhnya, maka itu harus dimulai.

Saya mencoba menggunakan ini di aplikasi Electron saya, itulah sebabnya saya tidak melihat alasan untuk menggunakan bundel web dan saya juga ingin tidak menginstal pemuat modul eksternal jika tidak diperlukan. Tapi ini membuatku gila. Bahkan tidak dapat menjalankan pengaturan TypeScript + Electron dasar meskipun keduanya dipuji di mana-mana sebagai solusi terbaik di luar sana. Itu gila, jujur ​​saja. Saya tidak tahu apakah saya kehilangan sesuatu tetapi tidak dapat menemukan solusi yang memadai lebih dari sekadar membuat frustrasi.

Dan jika itu benar-benar bukan saya, saya tidak mengerti mengapa masalah ini tidak terselesaikan dalam 3 tahun ...

Saya baru saja menyelesaikan tutorial TypeScript dan kemudian ketika saya mencoba membuat beberapa file ts saya menemukan masalah ini. Saya benar-benar baru di dunia js-ts ini jadi maafkan saya jika ada yang salah atau menyesatkan/salah informasi.

apa yang saya lakukan adalah, saat mengimpor

Saya baru saja meletakkan ekstensi .js di file ts dan kemudian ketika saya memeriksa intellisense, itu juga berfungsi ketika saya mentranspilasikannya menggunakan tsc, ekstensi .js juga ditambahkan ke file output yang dihasilkan.

Berikut yang saya lakukan.
tsc -p tsconfig.json

{
"compilerOptions": {
//"modul": "amd",
"modul": "es6",
"target":"es6",
"noImplicitAny": salah,
"hapusKomentar": benar,
"preserveConstEnums": salah,
//"berkas keluar": "js",
"outDir":"js",
"sourceMap": salah
},
"termasuk": [
"tesscript.ts"
]
}

Meskipun itu berhasil untuk saya.

Keraguan saya adalah karena tidak ada svgwrapper.js untuk diimpor
mengapa / bagaimana cara kerjanya? (Saya berasumsi itu tidak mempertimbangkan ekstensi)

Saya melampirkan tangkapan layar untuk referensi.

ts-js-ext-issue

@yogeshjog ini adalah persis bagaimana tsc dan seharusnya bekerja. Anda mengimpor modul dengan nama file yang akan dihasilkan. Apakah modul yang diimpor awalnya ditulis sebagai file .ts atau pasangan .d.ts / .js tidak boleh diamati dari modul yang diimpor.

@yogeshjog ini adalah persis bagaimana tsc dan seharusnya bekerja. Anda mengimpor modul dengan nama file yang akan dihasilkan. Apakah modul yang diimpor awalnya ditulis sebagai file .ts atau pasangan .d.ts / .js tidak boleh diamati dari modul yang diimpor.

Terima kasih! @justinfagnani untuk klarifikasi 👍

Anda mengimpor modul dengan nama file yang akan dihasilkan.

Tetapi TypeScript juga memungkinkan untuk menghilangkan ekstensi, yang tidak diizinkan menurut ECMAScript. Ia bahkan menghilangkan ekstensi saat menggunakan fitur auto-import di VSCode yang merupakan hal yang paling menyebalkan. Anda menulis beberapa JS dan TS mengatakan tidak apa-apa dan kemudian macet saat runtime.

Tetapi TypeScript juga memungkinkan untuk menghilangkan ekstensi

Saat menggunakan resolusi node. tsconfig setidaknya diatur untuk memungkinkan mode resolusi lain yang akan memperingatkan tentang ini, tetapi pemahaman saya adalah bahwa tim telah membiarkan dukungan modul asli diselesaikan sebelum menambahkan lebih banyak mode.

yang tidak diperbolehkan menurut ECMAScript.

ECMAScript tidak mengatakan apa pun tentang penentu impor. Itu diserahkan kepada lingkungan host seperti HTML dan Node.js. TypeScript mendukung resolusi node saat memuat modul, dan menafsirkan resolusi terhadap _output_ compiler, bukan _input_ compiler. Dengan cara ini penentu bekerja setelah kompilasi dan mereka berfungsi terlepas dari apakah Anda mencoba mengimpor modul yang dikompilasi atau tidak.

Karena TypeScript menggunakan resolusi Node yang akan melakukan pencarian jalur untuk mengubah './foo' info './foo.js' , './foo' valid. Tetapi resolusi Node tidak akan mengubah './foo.ts' menjadi './foo.js' , jadi './foo.ts' tidak valid.

Tapi itu dalam resolusi Node. Jika Anda mencoba menggunakan lingkungan lain seperti HTML atau dukungan modul asli Node, maka TypeScript dan host akan tidak setuju tentang apa yang valid.

Semoga dukungan modul asli cukup diselesaikan sekarang untuk TypeScript untuk menambahkan pengaturan resolusi lain.

@leontepe Anda tidak perlu bundler/loader. Anda dapat menggunakan https://github.com/Zoltu/typescript-transformer-append-js-extension/ (solusi pilihan saya) atau Anda dapat menambahkan .js ke semua pernyataan impor Anda (hati-hati: ini akan membuat kode Anda gagal di ts-node ).

@leontepe Anda tidak perlu bundler/loader. Anda dapat menggunakan https://github.com/Zoltu/typescript-transformer-append-js-extension/ (solusi pilihan saya) atau Anda dapat menambahkan .js ke semua pernyataan impor Anda (hati-hati: ini akan membuat kode Anda gagal di ts-node ).

@MicahZoltu Yah, terima kasih, tapi masih agak frustasi karena tidak hanya bekerja 'di luar kotak'. Seperti yang dikatakan @phaux , VSCode menyarankan penggunanya untuk membuat pernyataan impor tanpa ekstensi dan itu tidak berfungsi saat runtime. Saya benar-benar mempertanyakan kompetensi tim TypeScript di sini atau saya melakukan kesalahan selama ini dan benar-benar bodoh. Tapi siapa yang tahu...

Sunting: serius mempertimbangkan hanya menjatuhkan TypeScript untuk JavaScript + Babel pada saat ini.

Saya belum menulis aplikasi Electron, tetapi apakah ada kemungkinan membuatnya melakukan resolusi gaya Node, di mana ada algoritme untuk mencoba menyelesaikan impor yang mencoba beberapa hal dalam urutan tetap? Sepertinya tidak apa-apa mengingat semua sumber dimuat dari sumber daya lokal ...

Mungkin sudah waktunya untuk menambahkan resolusi modul baru ke TS? Node.js memiliki dukungan ESM asli sekarang, tetapi tanpa ekstensi eksplisit di jalur relatif itu memaksa untuk menggunakan --experimental-specifier-resolution=node flag, yang agak mengganggu. Ada juga Deno dan browser. Idealnya harus ada sesuatu seperti itu:
tsconfig.json:

{
    "compilerOptions": {
        "moduleResolution": "explicit",
        "strict": true
    }
}

lalu TypeScript:

import foo from './foo.ts'; // no ts(2691) here

kompilasi ke Javascript:

import foo from './foo.js';

"ketat": benar berarti banyak pekerjaan!
2020, masih belum diperbaiki, konyol.

Hanya menimpali untuk mengatakan bahwa masalah ini memblokir tim kami juga

Kami benar-benar ingin memiliki satu sumber yang dibuat untuk modul asli dan juga dapat dikonsumsi di node dan dengan webpack. Webpack tampaknya memiliki masalah jika Anda memasukkan .js secara manual ke dalam impor dalam kode TS Anda. Namun, Anda dapat membuat webpack bekerja jika Anda memasukkan ekstensi file .ts ke dalam impor Anda, tetapi tentu saja TypeScript mengeluh. Tidak memiliki ekstensi file menghasilkan tidak memiliki modul asli. Jadi, sepertinya tidak ada kombinasi yang memuaskan browser dan bundler. Jika kita dapat menulis .ts dalam impor kita dan menjadikannya .js dalam output, saya yakin masalah akan terpecahkan (dan Anda juga akan mendapatkan deno compat). Sesuatu seperti yang disarankan @evg656e sepertinya harus berfungsi.

@EisenbergEffect apakah ada bug yang diajukan terhadap WebPack untuk ini? Benar-benar terdengar seperti masalah WebPack yang menyimpang dari tsc normal.

@justinfagnani Saya tidak yakin apakah masalahnya ada di webpak, ts-loader, atau di tempat lain. Saya memang menghabiskan banyak waktu untuk mencoba mendapatkan pengaturan build yang optimal dan tidak menemukan solusi apa pun yang mencentang semua kotak. Mungkin ada cara untuk melakukannya dengan trafo khusus atau langkah pasca-pembuatan, tetapi saya enggan mengadopsi penyiapan non-standar karena dapat memengaruhi pengembang hilir secara negatif.

@EisenbergEffect jika pemuat TypeScript WebPack tidak mengizinkan Anda mengimpor file TypeScript melalui ekstensi .js seperti yang dilakukan tsc , maka itu adalah bug. Seperti yang Anda katakan, perilaku tersebut mencegah pembuatan sumber yang sama dengan WebPack dan tsc .

Mungkin sudah waktunya untuk menambahkan resolusi modul baru ke TS? Node.js memiliki dukungan ESM asli sekarang, tetapi tanpa ekstensi eksplisit di jalur relatif itu memaksa untuk menggunakan --experimental-specifier-resolution=node flag, yang agak mengganggu. Ada juga Deno dan browser. Idealnya harus ada sesuatu seperti itu:
tsconfig.json:

{
    "compilerOptions": {
        "moduleResolution": "explicit",
        "strict": true
    }
}

lalu TypeScript:

import foo from './foo.ts'; // no ts(2691) here

kompilasi ke Javascript:

import foo from './foo.js';

Orang-orang (misalnya, saya) akan senang membiarkan satu bagian kode bekerja di antara Node.js, Deno, dan Web secara bersamaan. Saya pikir ini akan menjadi tonggak besar untuk pemrograman TypeScript/JavaScript.

Jika Anda menggunakan vscode dan memerlukan solusi sementara, menambahkan ini ke settings.json tampaknya memperbaiki masalah:

"typescript.preferences.importModuleSpecifierEnding": "js"

Ini akan menambahkan .js ke jalur impor Anda (yang akan menyelesaikan file *.ts di src tanpa kesalahan, tetapi mempertahankan .js saat transpiling). Ini berguna saat menggunakan tsc tanpa bundler.

Sementara kami menunggu solusi tsc, perbaikan teknologi rendah untuk ini adalah

  1. Salin semua file sumber ke folder sementara
  2. Hapus ekstensi untuk impor dan ekspor sebelum membangun

Saya ingin membagikan one-liner ini seandainya orang lain dapat menggunakannya. Itu menyalin folder src/ ke tmp/ dan mengubah file di sana.

npx shx cp -r ./src/ ./tmp/ && npx rexreplace "(^§s*?(?:import|export).*?from§s+?(['\"]).*?)§.ts§2" €1€2 './tmp/**/*.{ts,js,tsx,jsx}'

Sebagai bagian dari skrip build di package.json (setelah melakukan yarn add --dev shx rexreplace ) bisa terlihat seperti ini

"scripts":{
  "build": "yarn build-esm && yarn build-tsc",
  "buil-esm": "...Whatever you normally do...",
  "build-tsc": "shx mkdir -p tmp && shx cp -r ./src/* ./tmp && rexreplace \"(^§s*?(?:import|export).*?from§s+?(['\\\"]).*?)§.ts§2\" €1€2 './tmp/**/*.{ts,js,tsx,jsx}' && tsc src/index.ts && shx rm -r ./tmp"
}

Saat ini saya menjauhkan .js dari jalur impor di sumber TypeScript, untuk membuat Jest senang.
Kemudian, saya memiliki langkah pemrosesan pos untuk menambahkan .js .
Peta sumber tidak didukung dengan metode ini.

tsc -b tsconfig-solution.json -w --listEmittedFiles \
  | node mk/build-post.js

Skrip pemrosesan pasca build-post.js melakukan hal berikut.

Tambahkan .js ke import dan export dari jalur relatif

Sebagai contoh,

export { X } from "./first";
import { Y } from "./second";

menjadi

export { X } from "./first.js";
import { Y } from "./second.js";

Perhatikan bahwa saya tidak menggunakan index.ts di mana saja, melainkan menggunakan mod.ts mengikuti konvensi Deno. Jadi, saya tidak perlu mempertimbangkan kasus menambahkan /index.js .

Ubah import menjadi require untuk paket CommonJS

Kode saya berjalan pada Node ^12.17 dan ^14.1, dalam mode modul. Saya hanya menerbitkan Modul ES.
Namun, banyak dependensi masih memiliki CommonJS di bidang "main" mereka.
Jadi, saya harus mengubahnya ke CommonJS, kecuali modul bawaan NodeJS.

Sebagai contoh,

import { Server as WsServer } from "ws";

menjadi

import { createRequire } from "module";
const require = createRequire(import.meta.url);
const { __importDefault } = require("tslib");

const { Server: WsServer } = require("ws");

Tapi kemudian, webpack tidak senang dengan require ini, jadi saya harus menggunakan:

/// #if false
import { createRequire } from "module";
const require = createRequire(import.meta.url);
const { __importDefault } = require("tslib");
/// #endif

/// #if false
const { Server: WsServer } = require("ws");
/*
/// #else
import { Server as WsServer } from "ws";
/// #endif
/// #if false
*/
/// #endif

Di webpack, paket apa pun yang mengimpor proyek saya harus menggunakan ifdef-loader , dan kemudian webpack akan melihat baris import asli.

Kami juga terkena ini dan saya tidak mengerti bagaimana ini tidak diperbaiki 3 tahun setelah dilaporkan.
Kami menggunakan WebStorm sehingga pengaturan khusus VSCode tidak akan berfungsi.
Menggunakan skrip terpisah untuk memperbaiki output itu konyol.
Ini akan berfungsi tanpa harus menggunakan alat pihak ketiga.

+1

Ini adalah solusi saya menggunakan situs web asp.net core 3.1 (mungkin berfungsi pada versi yang lebih rendah)
Di startup.cs:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseRouting();

            var rewriteOptions = new RewriteOptions();
            rewriteOptions.AddRewrite(@"^js/(.+)", "js/$1.js", skipRemainingRules: true);

            app.UseRewriter(rewriteOptions);

            app.UseStaticFiles();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapGet("/", async context =>
                {
                    await context.Response.WriteAsync("Hello World!");
                });
            });
        }

Middleware penulisan ulang akan menambahkan ekstensi ".js" ke setiap permintaan yang menargetkan folder /js.
Peringatan: urutan middleware penting di sini, UseStaticFiles harus ditempatkan setelah UseRewriter atau tidak akan berfungsi.

Seperti semua orang di sini, saya lebih suka solusi di luar kotak tetapi sampai saat itu ...

Mungkin sudah waktunya untuk menambahkan resolusi modul baru ke TS? Node.js memiliki dukungan ESM asli sekarang, tetapi tanpa ekstensi eksplisit di jalur relatif itu memaksa untuk menggunakan --experimental-specifier-resolution=node flag, yang agak mengganggu. Ada juga Deno dan browser. Idealnya harus ada sesuatu seperti itu:
tsconfig.json:

{
    "compilerOptions": {
        "moduleResolution": "explicit",
        "strict": true
    }
}

lalu TypeScript:

import foo from './foo.ts'; // no ts(2691) here

kompilasi ke Javascript:

import foo from './foo.js';

Saya mengatur aturan node/file-extension-in-import di eslint-plugin-node ke konfigurasi linting dengan gagasan untuk menambahkan ekstensi secara manual ke pernyataan impor (karena lebih baik seperti itu) dan "moduleResolution": "node" di TypeScript config dan yang bisa saya lihat hanyalah ts(2691) .

Semoga apa yang dikatakan @evg656e layak untuk diterapkan.

Saya tidak percaya ini masih menjadi masalah.

ketika Anda menggunakan
"baseUrl": ".", "paths": { "/*": ["./*"] },

anda dapat melakukan impor modul absolut seperti:
`impor ws dari "/ hei/koneksi";

tetapi ketika menambahkan ekstensi ".js", tiba-tiba kompiler tidak lagi menemukan deklarasi connection.ts dan berkata:

Could not find a declaration file for module '/hey/connection'. '/home/tobi/Documents/JITcom/Code/Libs/Test_Browser/hey/connection.js' implicitly has an 'any' type.

menggunakan jalur relatif semuanya berfungsi dengan baik.

Tolong perbaiki ini

Saya juga ingin perbaikan untuk ini.

Terima kasih.

Sungguh konyol bahwa ini masih menjadi masalah! :00

Saya akhirnya memutuskan untuk beralih ke TypeScript dan ini adalah salah satu masalah pertama yang saya hadapi. Itu merusak resolusi modul dalam implementasi asli Node, dan saya hanya bisa menyiasatinya dengan menggunakan paket esm yang tampaknya lebih fleksibel dalam menerima nama tanpa ekstensi, atau (anehnya) menggunakan ekstensi .js di jalur impor di dalam file .ts saya bahkan ketika impor merujuk ke file .ts atau .tsx. Saya tidak yakin mengapa kompiler TypeScript menerimanya, tetapi setidaknya output build kemudian menyertakan ekstensi .js. Solusi yang sangat hacky.

Saya bahkan tidak banyak menggunakan TypeScript di sisi klien akhir-akhir ini, tidak terlalu memengaruhi kualitas kode saya dan membuat segalanya menjadi lebih sederhana. Mungkin JavaScript akan memiliki tipe opsional dari satu titik dan masalah ini tidak akan menjadi masalah lagi.

Saya meninggalkan ekstensi pada jalur impor, untuk membuat Jest dan Webpack senang.
Ketika saya mengkompilasi, saya memanggil tsc --listEmittedFiles dan menyalurkan output ke skrip pasca-pemrosesan. Skrip itu menambahkan ekstensi .js , untuk membuat Node (dalam mode modul) senang.
https://github.com/yoursunny/NDNts/blob/fa6b2eb68a9f32a6a2e24e5475275f803236b8f8/mk/build-post.js

@kj

(anehnya) menggunakan ekstensi .js di jalur impor di dalam file .ts saya bahkan ketika impor merujuk ke file .ts atau .tsx. Saya tidak yakin mengapa kompiler TypeScript menerimanya, tetapi setidaknya output build kemudian menyertakan ekstensi .js. Solusi yang sangat hacky.

Ini tidak aneh dan jelas tidak hacky, dan bekerja sempurna dengan browser dan resolusi modul asli Node.

Sumber daya yang Anda impor _is_ file .js. Jenisnya bisa dalam file .ts atau dalam file .d.ts. File .d.ts bahkan tidak perlu menjadi saudara dari modul .js, dan tidak perlu ada hubungan 1-1 antara file .d.ts dan file .js.

Mengimpor modul .js adalah opsi paling andal dan stabil yang bisa dipilih tsc. Kalau tidak, akan ada kasus di mana Anda mengimpor tipe dan tsc tidak tahu cara yang benar untuk menulis ulang mereka ke jalur modul yang sebenarnya.

@justinfagnani Ah, saya pikir itu masuk akal. Saya tidak bermaksud menyiratkan bahwa apa pun yang dilakukan TypeScript di sini adalah peretasan (saya tidak dalam posisi untuk membuat klaim seperti itu), hanya saja saya merasa bahwa apa yang saya lakukan mungkin tidak biasa. Kurasa aku memikirkannya dengan cara yang salah. Bukan TypeScript yang mengimpor modul, apa pun yang mengevaluasi output build (atau apakah saya salah paham)? Dalam hal ini saya dapat melihat mengapa itu akan bekerja dengan cara ini.

Sumber daya yang Anda impor _is_ file .js

Anda mengacu pada modul yang dibangun di sini kan? Bukan file .js di direktori sumber, tetapi versi bawaan dari modul .ts?

Bukankah jika Anda secara eksplisit menentukan ekstensi .ts atau .tsx di jalur modul, maka hasilnya akan menggantikan .js?

Saya pikir mungkin ada kesalahpahaman tentang apa yang terjadi @kj. Saat Anda menentukan ekstensi .ts tanpa mengkompilasi kode Anda, itu merujuk ke file ts. Tetapi ketika Anda mengkompilasi menggunakan tsc, itu mengubah konten file ts menjadi file js yang dapat dieksekusi di lingkungan tempat Anda berada (node ​​atau browser).

Saya mengerti bahwa @mkay581 , tetapi katakan saya memiliki baris ini di file foo.ts:

import { Component } from './Component.js';

'Komponen.js' yang saya maksud sebenarnya adalah 'Komponen.tsx' pada sistem file (tidak ada file .js, kecuali TypeScript memahami bahwa ini merujuk pada versi file yang akhirnya diubah?), belum TypeScript menerima ini dengan baik dan baris impor yang sama kemudian ada di output (dengan ekstensi .js yang kemudian berfungsi dengan Node atau browser).

Cara TypeScript tradisional (AFAIK) adalah dengan menentukan baris impor itu tanpa ekstensi, sebagai:

import { Component } from './Component';

Itu jelas dikompilasi dengan baik juga, kecuali baris impor dalam file .js yang ditranspilasikan tidak menyertakan ekstensi .js pada './Component', yang diperlukan oleh lingkungan tertentu (dan mungkin kedengarannya seperti spesifikasi, meskipun saya belum' t membacanya untuk memastikan).

Di sisi lain, jika saya menentukan baris dengan nama file sebenarnya dari file sumber:

import { Component } from './Component.tsx';

Kemudian TypeScript tidak mengenali jalur dan menyarankan agar saya mencoba baris impor tanpa ekstensi file (jika saya ingat, saya tidak di depan komputer saya sekarang).

Jadi, contoh pertama terasa agak aneh bagi saya, saat saya menulis TypeScript, saya berharap dapat mengimpor dengan ekstensi .ts atau .tsx, namun hanya menerima jalur tanpa ekstensi (yang tampaknya bertentangan dengan implementasi lain dari sistem modul ES) atau dengan ekstensi .js yang hanya dapat merujuk ke file output karena saya tidak memiliki file sumber tersebut.

@justinfagnani

Sumber daya yang Anda impor _is_ file .js.

Saya tidak tahu bagaimana tsc bekerja tetapi itu tidak terdengar benar bagi saya. Saat Anda menulis kode, belum ada file .js. Itu tugas kompiler untuk membuatnya.

TS bertindak sebagai lapisan abstraksi di atas JS dan file .js adalah output dari langkah kompilasi. Mengandalkan mereka berada di sana dengan ekstensi khusus itu tampaknya mematahkan abstraksi, IMO.

Dengan kata lain, ketika Anda menggunakan C atau C++ Anda tidak #include file .o dalam kode Anda, Anda menyertakan .h atau paling banyak .c atau .cpp .

Saya bersedia menerima penjelasan yang masuk akal untuk perilaku ini di TypeScript tetapi kecuali saya melewatkan sesuatu, yang ini sepertinya bukan itu.

@kj

Itu tidak aneh dan jelas tidak hacky

Sulit tidak setuju. Bagi saya itu adalah definisi aneh dan hacky. Apa yang Anda lakukan di sini adalah referensi file hipotetis. File yang tidak dijamin ada. (Misalnya ketika bundling kode, menggunakan AssemblyScript, atau deno) Anda mengasumsikan format output. Tetapi ketika menulis kode agnostik (misalnya modul pihak ketiga), itu adalah hal yang _berbahaya_ untuk diasumsikan.

@borfast @frzi Ya pada dasarnya itulah yang saya rasakan tentang hal itu, dan saya senang melihat bahwa saya bukan satu-satunya yang tidak merasa nyaman dengan ini. Saya hanya mencoba untuk tidak membuat terlalu banyak asumsi yang begitu baru untuk TypeScript!

@frzi

Apa yang Anda lakukan di sini adalah mereferensikan file hipotetis. File yang tidak dijamin ada

Tidak hipotetis, tsc tahu itu akan menghasilkannya. Dijamin ada, saat menggunakan tsc.

Cara lain untuk melihatnya adalah jika Anda mengimpor file .ts, Anda mengimpor file yang tidak akan ada di sana setelah kompilasi.

saat menggabungkan kode

Bundler dijalankan setelah tsc

@kj menyebutkan file .tsx, dan mereka lebih mengarahkan poin saya ke rumah. .tsx hanya ada untuk memberi sinyal kepada kompiler modul itu, _locally_, bahwa modul tersebut berisi JSX. Importir modul tidak perlu tahu bahwa ada BEJ dalam file, dan mereka tidak tahu setelah kompilasi. File dapat dipindahkan dengan mulus antara pasangan .tsx, .ts, dan .js/.d.ts.

Katakanlah Anda mengimpor file .ts:

import {Component} from './component.ts';

Dan Anda kemudian ingin menggunakan JSX untuk komponen tersebut, jadi Anda mengganti namanya menjadi component.tsx. Haruskah semua impor gagal? Katakanlah Anda bermigrasi dari .ts ke .js/.d.ts, haruskah impor gagal lagi?

@borfast

TS bertindak sebagai lapisan abstraksi di atas JS dan file .js adalah output dari langkah kompilasi. Mengandalkan mereka berada di sana dengan ekstensi khusus itu tampaknya mematahkan abstraksi, IMO.

Abstraksinya tidak selengkap yang Anda maksudkan di sini. Anda dapat mengimpor file .js dari dalam atau luar proyek TS Anda. Anda dapat menambahkan jenis ke file .js dengan file .d.ts yang ada di mana saja dalam proyek Anda. File .js adalah yang asli setelah dikompilasi. Segala sesuatu yang lain hanya membantu kompiler.

@justinfagnani Saya agak bingung dengan apa yang Anda katakan, tetapi mengapa TypeScript tidak berasumsi bahwa jika Anda memberikan jalur impor dengan .ts atau .tsx, itu akan menghasilkan file .js untuk modul itu dan karena itu harus mengganti ekstensi yang terakhir dalam output?

@justinfagnani

Tidak hipotetis, tsc _knows_ itu akan menghasilkannya. Dijamin ada, saat menggunakan tsc.

Tapi ada simetri tersirat di sini yang tidak Anda akui.

“Jaminan” yang Anda sebutkan ini berlaku dua arah. Jika, seperti yang Anda katakan, “tsc _knows_ it'll generate [js files]”, maka itu adalah pertanyaan yang sama validnya untuk ditanyakan: “Nah, lalu mengapa tsc TIDAK bertindak atas jaminan ini dan menerapkan ekstensi .js yang _knows_ adalah hilang dari js yang dikompilasi?”

Menafsirkan fakta bahwa "tsc menjamin file js" berjalan dua arah.

Jadi saya setuju, @justinfagnani , interpretasi Anda _is_ valid, dari sudut pandang tertentu. Tetapi interpretasi yang berlawanan adalah bahwa "tsc harus _bertindak berdasarkan pengetahuannya_ dan melakukan proses ini untuk pengembang". Dan yang mengganggu saya tentang seluruh perdebatan ini sejak awal adalah bagaimana _secara negatif_ interpretasi ini diterima, hampir sampai diejek. Ini tidak masuk akal.

Pada akhirnya, perdebatan ini adalah tentang _keputusan estetis, bukan keputusan logis_. Dan harapan saya adalah bahwa nada suara yang ampliatif dan akomodatif — seperti yang sesuai dengan _opini_ estetika (bukan deduksi logis) — dibawa untuk menanggung masalah ini oleh para pencelanya.

Singkatnya, tolong akui pertanyaan OP adalah interpretasi yang benar-benar valid - mungkin bersama dengan Anda sendiri. Tidak perlu perdebatan sengit.

Terima kasih

@justinfagnani

Cara lain untuk melihatnya adalah jika Anda mengimpor file .ts, Anda mengimpor file yang tidak akan ada di sana setelah kompilasi.

Tentu saja tidak, seperti halnya file .h tidak didistribusikan dengan program C yang dapat dieksekusi. Itulah intinya: Anda memberi tahu kompiler untuk menyertakan file sumber , bukan file yang dikompilasi .

Oke, saya terlalu banyak spam dengan percakapan ini untuk mengabaikannya lebih lanjut.
Pernyataan import BUKAN bagian dari TypeScript, itu bagian dari lingkungan JavaScript yang mengeksekusinya. Sekarang, kata kuncinya di sini adalah lingkungan JavaScript , karena INI adalah yang menyelesaikan jalur. Tunjukkan pada saya satu aplikasi yang dalam runtime mengimpor dan mengeksekusi file .ts (tentu, mungkin ada beberapa, tetapi itulah yang saya sebut hacky).
TypeScript memungkinkan penambahan ekstensi .js karena memungkinkan JavaScript asli di dalam file sumbernya. tidak satu pun dari browser node.js akan mengeksekusi file .ts, bahkan ts-node mentranspilasikan file .ts dengan cepat, hanya menyimpan hasilnya di memori alih-alih menuliskannya ke hard drive (tidak meretas sama sekali ?).

Sekarang, perbaikan tsc yang tepat adalah:

  • kami memiliki file .ts
  • kami mereferensikannya di file lain
  • tsc mengubah file .ts itu menjadi file .js
  • tsc kemudian menulis ulang semua referensi langsung ke file .ts dengan file .js (ia tahu persis bagaimana transpilasinya sehingga dapat memperbaruinya dengan benar)

Masalah: "web dev modern" bukan web dev asli dan menggunakan cara mengimpor node.js, melewatkan ekstensi (dan seluruh jalur file). tsc sekarang tidak tahu lagi seperti apa outputnya, karena mengimpor my-awesome-module/test bisa apa saja, mulai dari file test.js di node-modules/my-awesome-module , hingga file index.js di dalam folder test di node-modules/my-awesome-module , diakhiri dengan beberapa penulisan ulang lokal dengan file non-js seperti ./local-mocks/my-awesome-module/mock.json .

Di sinilah masalah muncul: bagaimana tsc dapat mengetahui apa konfigurasi webpack/rollup/super-awesome-new-and-shiny-bundler yang funky untuk proyek khusus Anda?

Sekali lagi: Saya setuju untuk tsc untuk menulis ulang jalur impor, tetapi itu hanya akan berfungsi untuk proyek-proyek sederhana, dan membuatnya berfungsi hanya untuk proyek-proyek sederhana (yang saat ini merupakan minoritas karena bahkan halaman presentasi sederhana yang digunakan bereaksi dengan konfigurasi webpack yang direkayasa ulang) tidak layak menghabiskan waktu, jika itu dapat dilakukan dengan skrip tertulis khusus yang sederhana.

Sekali lagi: Saya setuju untuk tsc untuk menulis ulang jalur impor, tetapi itu hanya akan berfungsi untuk proyek-proyek sederhana, dan membuatnya berfungsi hanya untuk proyek-proyek sederhana (yang saat ini merupakan minoritas karena bahkan halaman presentasi sederhana yang digunakan bereaksi dengan konfigurasi webpack yang direkayasa ulang) tidak layak menghabiskan waktu, jika itu dapat dilakukan dengan skrip tertulis khusus yang sederhana.

Bagaimana Anda melakukannya dalam proyek sederhana tanpa webpack, hanya dengan tsc maksud saya?

Saya membaca komentar semua orang dan tampaknya menjadi ketidaksepakatan mendasar tentang harapan penggunaan TypeScript di sini.

Ketika file sumber .ts merujuk file .js, masalahnya telah dimulai.

TypeScript dibuat untuk ~menjalankan~ mengkompilasi file .ts sumber -- bukan file .js. Jika seorang dev ingin menggunakan TypeScript pada proyek mereka, mereka harus mengonversi proyek _seluruh_ mereka menjadi TypeScript dan tidak meninggalkan file .js yatim piatu dan mencoba untuk mereferensikannya. Dan jika Anda tidak punya waktu untuk mengubah konten dalam file js ke sintaks TypeScript, cukup ganti nama file js menjadi file ts (atau gunakan pemetaan jalur TS untuk memetakan impor ke file .js). Masalah terpecahkan. :man_mengangkat bahu:

EDIT: Memperbaiki "jalankan" menjadi "kompilasi", yang saya maksudkan tetapi saya dapat melihat bagaimana itu mungkin ditafsirkan secara berbeda.

@ mkay581 TypeScript tidak pernah dimaksudkan untuk menjalankan apa pun, hanya untuk menampilkan file JS.

@valeriob Proyek sederhana mungkin paling banyak memiliki beberapa file, yang tidak perlu dibundel. Peramban saat ini memiliki impor bawaan, tidak perlu menyiasatinya. Maka itu akan menjadi sesederhana mendengarkan acara navigasi di browser, lalu memetakan setiap acara ke rute yang cocok, setiap rute dapat mengimpor data dengan fetch dan setelah dikembalikan dapat dirender dengan mesin templating yang tidak dikompilasi (lit- html, HyperHTML, atau yang lebih lama seperti Moustache, Handlebars, Pug dll). Selesai, tidak perlu mewah webpack, kerangka kerja, atau pustaka utilitas apa pun, bahkan pendengar, regexp, fetch, promise, dan mesin templating js sederhana.

Terima kasih @Draccoz , bisakah Anda memberi tahu saya cara membuat skenario sederhana ini berfungsi? https://github.com/valeriob/Typescript_Non_SPA
Ini adalah file .ts sederhana yang mereferensikan perpustakaan JS (rxjs sebagai contoh) dan saya ingin menggunakannya sebagai modul di halaman html.

@valeriob Ini tidak sepele seperti yang seharusnya. Sebagian besar perpustakaan pihak ke-3 bahkan ketika mereka menyatakan bahwa mereka kompatibel dengan Modul ES, mereka tidak berada di dunia browser.
RxJS adalah sesuatu yang paling saya minati ketika membawanya ke aliran asli, tetapi mereka menunggu tiket ini diselesaikan sebelum mereka memutuskan untuk mengimplementasikannya sendiri (lucu...).
Dalam arsitektur yang saya rancang, saya awalnya menggunakan sed untuk memperbaiki semua impor, tetapi kemudian berubah pikiran untuk menggunakan server dev sederhana dengan penulisan ulang jalur. Konsep saya adalah tidak memiliki ketergantungan eksternal di aplikasi saya selain rxjs, TypeScript, dan lit-html (node_modules dengan 4 folder dan tes/pembuatan CI cepat ULTRA). Jika TS menulis ulang jalur, itu akan menghilangkan kebutuhan untuk server saya, meskipun tetap sekitar 90 baris kode. Ini open source, jika ada yang ingin tautan tanyakan atau periksa organisasi di profil saya.

Mengenai halaman sederhana, saya merujuk ke halaman yang tidak benar-benar membutuhkan perpustakaan apa pun, seperti menekan url -> mengambil data -> menampilkannya -> ulangi.

Tidak perlu menggunakan perpustakaan apa pun di Js adalah fantasi murni karena Js tidak memiliki perpustakaan dasar.

Skenario sederhana adalah yang saya tautkan, dan itu tidak berfungsi. Ini juga merupakan skenario paling umum untuk ppl yang tidak ingin terjun ke dunia webpack/kompilasi gila yang memperumit banyak hal tanpa manfaat nyata, sangat membatasi pilihan Anda, membuat para pengembang melawan alat lebih dari menulis aplikasi Anda, dan memperlambat pengembang Anda lingkaran.

Banyak senam mental yang terjadi di sini untuk menyangkal bahwa masalah ini ada dan itu merupakan perhatian penting bagi produktivitas banyak pengembang.

Menjelaskan bahwa itu _tidak boleh menjadi masalah_ tidak _memecahkan masalah_. Perangkat lunak harus sesuai dengan model mental pengguna, tidak memaksakan model implementasinya sendiri kepada pengguna. (barang UX)

Jika pengguna mengkonseptualisasikan tsc sebagai kompiler mirip-C, sesuai @borfast , maka itu adalah mode mental istimewa yang perlu diakomodasi, terlepas dari apa detail implementasi tsc.

Pertanyaan OP memiliki 200+ jempol, lebih dari semua masalah lain di repo.

Masalah ini layak mendapatkan suara masyarakat. Harap pertimbangkan untuk memulai polling.

Jika sebagian besar pengguna ingin tsc menulis ulang impor mereka, maka itu adalah jawaban yang tepat. Setidaknya itulah cara UX dalam memandang sesuatu.

Ini bahkan lebih sederhana dari itu, jika TypeScript sebagai bahasa merupakan superset dari JavaScript, output dari tsc (bahkan bukan saklar file output tunggal) harus dapat dicerna oleh JavaScript itu sendiri.

@weoreference jika Anda mendefinisikan dengan cara yang jelas (bukan menulis kode, hanya mendesain) bagaimana PERSIS seharusnya menulis ulang jalur, dengan mempertimbangkan banyak lingkungan (node.js, browser), beberapa kemungkinan konfigurasi bundler (menyelidiki semua fitur saat ini, yang direncanakan, dan kemungkinan masa depan dari webpack, rollup and parcel dan bundler lainnya) maka yakinlah, maka saya yakin tim TypeScript akan penuh di pihak Anda.

Jika Anda tidak mau melakukannya atau berpikir itu terlalu sulit, berhentilah meminta mereka untuk membuat fitur yang tidak dapat dijelaskan oleh siapa pun, seperti "Saya tidak peduli bagaimana caranya, tetapi buatlah sapi ini terbang"...

@Draccoz , Anda ingin mobil Anda memindahkan persneling sehingga Anda dapat mengendarainya lebih cepat dari 10 Km/jam, tetapi saya yakin Anda tidak pernah diminta oleh pabrikan untuk mempelajari cara kerja kereta roda gigi, apalagi mendesainnya.

Adapun masalah bundler dan yang lainnya, mengapa itu menjadi penghambat untuk ini?

Dengar, saya hanya ingin menggunakan modul ES, saya tidak ingin berurusan dengan semua kegilaan Babel dan Webpack. Mengapa ini tidak bisa menjadi opsi kompiler opsional yang hanya mengubah ekstensi file menjadi .js? Jika perilaku ini bertentangan dengan opsi konfigurasi lain yang ditetapkan oleh pengguna, itu harus dinonaktifkan secara otomatis, atau peringatan/kesalahan akan ditampilkan dan kompilasi dihentikan ketika tsc dijalankan, sehingga pengguna tahu bahwa mereka perlu mengubah konfigurasi.

Saya benar-benar tidak mengerti mengapa ini tidak mungkin.

@Draccoz Halo :) Yah, seperti yang saya lihat, Anda menanyakan dua hal:

  1. Bagaimana itu bisa diimplementasikan

  2. Bagaimana saya, pengembang, dapat memberi sinyal kepada tsc bahwa saya ingin impor diganti dengan cara tertentu, untuk lingkungan khusus saya

Berikut adalah pikiran saya.

  1. Silakan lihat balasan @borfast ; ini adalah jawaban "tingkat tinggi", tetapi ringkas :)

  2. Mungkin saya bisa memberikan tanda ke tsc/tsconfig, seperti "renameImports":true, atau sinyal lain yang diambil oleh tsc. Jika lebih presisi diperlukan, maka mungkin bendera tidak boleh Boolean melainkan mengambil string, mungkin seperti ini:

standardImportExtension: 'js'

jadi semua impor tanpa ekstensi file default ke .js

Kesimpulan:
Fungsionalitas ini tampaknya sulit untuk diterapkan karena Anda menganggap bahwa Q2 (skema penggantian nama impor) perlu diketahui terlebih dahulu oleh Q1 (yaitu oleh tsc). Tapi sebenarnya, tidak. Saya, pengembang manusia, dapat dengan mudah memasok "pengetahuan dunia" ini ke tsc tanpa perlu mengetahui cara kerja webpack/browser/dll. Semua ini dengan bendera sederhana.

@borfast Transmisi tidak diminta oleh pengguna, itu disediakan dengan mobil oleh pabrikan, pengguna hanya setuju itu adalah fitur baru dan mulai menggunakannya - maaf, ini bukan argumen yang tepat. Dibandingkan dengan pengguna - contoh produsen mobil Anda, ini lebih seperti "Saya ingin mobil saya menjadi mobil listrik penuh dengan jangkauan 100k mil dan kecepatan tertinggi mencapai kecepatan jet. Saya tidak peduli bagaimana mencapainya, saya menginginkannya dan itu saja - titik.
@weoreference sedikit salah paham dalam pertanyaan saya. Saya bertanya tentang: bagaimana membuat tsc mengerti apa yang ditunjukkan oleh path? Apakah ini file js secara langsung? Atau apakah itu folder dengan index.ts di dalamnya? Atau apakah itu modul dengan package.json yang menampung bidang main ? Atau bidang esnext? Atau yang lain yang tidak standar? Atau apakah itu jalur yang ditulis ulang oleh webpack? Atau gulung? Kalo ada dimana confignya? Apakah itu bundler lain mungkin? Beberapa kurang dikenal? Dan apa kasus penggunaan lain yang tidak saya pikirkan dalam kalimat di atas?

Mungkin saya bisa memberikan tanda ke tsc/tsconfig, seperti "renameImports":true, atau sinyal lain yang diambil oleh tsc.

@weoreference dapatkah Anda belum melakukan ini dengan pemetaan jalur ? Opsi paths dalam file TSconfig memberi kita kontrol untuk memetakan jalur impor ke file JS. Maaf jika saya salah mengartikan.

@Draccoz Terima kasih atas balasan Anda, tolong beri tahu saya

Dan apa kasus penggunaan lain yang tidak saya pikirkan dalam kalimat di atas?

Oh ya, akan sangat sulit bagi tsc untuk memiliki pengetahuan tentang semua kombinasi alat lingkungan/bangunan ini.

Tetapi tsc dapat memiliki utilitas sederhana yang membantu pengembang menutupi _sebagian besar_ kasus penggunaan, dan ini adalah nilai konfigurasi “standardImportExtension” yang saya jelaskan.

Tentu saja, di sinilah masalah "jaminan". Sebelumnya di utas ini, dikatakan bahwa tsc harus "menjamin" bahwa js yang dikompilasi sebenarnya akan berjalan [di beberapa lingkungan].

Yah... mungkin ini komitmen yang terlalu sulit. Memang, sangat sulit bagi tsc untuk menjamin js akan berjalan [di beberapa lingkungan], karena, seperti yang baru saja Anda jelaskan, lingkungan itu sangat sulit untuk didefinisikan dalam lanskap js saat ini.

Tetapi utilitas flag sederhana yang diusulkan oleh @borfast memecahkan _sebagian besar_ kesalahan impor js yang dihadapi oleh pengguna baru yang mencoba tsc.

Penggunaan lanjutan, yang seperti yang Anda sebutkan terdiri dari semua pertimbangan ini —-

Apakah ini file js secara langsung? Atau apakah itu folder dengan index.ts di dalamnya? Atau apakah itu modul dengan package.json yang memegang bidang utama? Atau bidang esnext? Atau yang lain yang tidak standar? Atau apakah itu jalur yang ditulis ulang oleh webpack? Atau gulung? Kalo ada dimana confignya? Apakah itu bundler lain mungkin?

— yah, penggunaan itu, memang dapat diserahkan kepada skrip pengguna khusus, bundler, dan alat lainnya.

Tetapi hanya karena penggunaan tingkat lanjut sulit untuk diselesaikan tidak berarti kita harus menghindari penyelesaian kasus yang mudah.

Dan kasus termudah adalah menambahkan ekstensi .js ke impor; yang dapat kita pecahkan, dan harus dipecahkan.

@weoreference jadi saya tidak menyukai Anda karena mengajukan pertanyaan dan mencoba membantu dan kemudian Anda mengabaikan pertanyaan itu. Sepertinya Anda hanya ingin berdebat dan berdebat alih-alih benar-benar maju ke solusi yang produktif. Anda telah meremehkan upaya semua orang untuk melakukannya. Pesan terakhir untuk saya di thread ini. Maaf untuk semua spamming, semuanya.

@weoreference lihat di awal percakapan ini, di komentar @DanielRosenwasser . Dia menjelaskan mengapa mereka tidak menerapkannya ("saat ini"? pemberian harapan yang tidak berguna). Setelah pernyataannya, tidak ada seorang pun dari TypeScript yang mengomentari topik tersebut lebih lanjut. Bagi saya diskusi ini harus ditutup dan Microsoft harus secara resmi menyatakan sikap mereka. Periode.
Hanya sebagai catatan tambahan - secara pribadi saya semua untuk fitur itu, akan menyederhanakan BANYAK. Kehilangan harapan saya karena saya juga memahami argumen tim TypeScript.

@weoreference

Tidak hipotetis, tsc tahu itu akan menghasilkannya. Dijamin ada, saat menggunakan tsc.

Tapi ada simetri tersirat di sini yang tidak Anda akui.

“Jaminan” yang Anda sebutkan ini berlaku dua arah. Jika, seperti yang Anda katakan, "tsc tahu itu akan menghasilkan [file js]", maka itu adalah pertanyaan yang sama validnya untuk ditanyakan: "Nah, lalu mengapa tsc TIDAK bertindak atas jaminan ini dan menerapkan ekstensi .js yang diketahuinya hilang dari js yang dikompilasi?”

Simetri tidak berlaku sebenarnya. Ini tidak sesederhana hanya "menerapkan ekstensi .js" - tsc harus menyelesaikan dan menulis ulang specifier, dan resolusi mungkin bergantung pada deklarasi tipe. TypeScript dan Babel mendukung mode kompilasi modul tunggal (isolatedModules untuk tsc) dan dalam hal ini jika Anda mengimpor tipe alih-alih JavaScript, tsc harus memuat deklarasi tipe untuk menentukan di mana file .js yang sesuai akan berada, untuk menulis ulang penentu. Untuk menjaga hal-hal tetap konsisten dan tidak memiliki kasus tepi, yang paling sederhana adalah hanya mendukung pengimporan file .js yang ada sebelum kompilasi atau merupakan hasil yang diketahui dari proyek saat ini.

@justinfagnani @Draccoz Terima kasih; baiklah, ya saya mengerti.

Komentar terakhir saya: "hanya karena kasus sulit tidak dapat diselesaikan bukan berarti kami tidak dapat menyelesaikan kasus yang mudah."

Terima kasih

Saya telah berasumsi bahwa TypeScript bertentangan dengan spesifikasi di sini (dan menghasilkan JavaScript yang tidak valid), tetapi saya tidak dapat menemukan di mana pun dalam spesifikasi yang benar-benar mengharuskan jalur impor sama persis dengan nama file (dengan ekstensi). Sangat sulit untuk dicerna, jadi saya tidak sepenuhnya percaya diri, tetapi yang dapat saya temukan hanyalah bahwa spesifikasinya memerlukan 'ModuleSpecifier' di 'FromClause' menjadi 'StringLiteral'. Tampaknya definisi yang sangat longgar, tetapi saya kira itu memungkinkan fleksibilitas dalam resolusi modul di banyak lingkungan berbeda di mana ECMAScript ada. Adakah yang bisa mengkonfirmasi apakah saya membaca ini dengan benar? Jika ini benar-benar masalahnya, saya harus melunakkan pendirian saya terhadap cara TypeScript menangani ini. Meskipun, saya masih lebih suka ada lebih banyak interoperabilitas antara TypeScript, Node, dan web. Situasi saat ini tidak ideal.

Saya sampai pada masalah ini setelah membaca ini . Masalah itu memberi saya kesan bahwa sistem Node beroperasi seperti itu (sangat cocok dengan nama file) karena spesifikasi ES, tetapi saya dapat melihat sekarang bahwa saya salah membaca itu (mereka tidak mengacu pada spesifikasi ES), dan mungkin juga Node, atau TypeScript sebenarnya melakukan sesuatu yang 'salah'. Kemudian, masalah ini benar-benar tentang ketidakcocokan antara pendekatan yang sama validnya untuk resolusi modul antara lingkungan yang berbeda. Namun, jelas lingkungan target utama TypeScript adalah Node dan web, dan meskipun Node secara teoritis dapat mengubah pendekatan mereka, saya tidak berpikir kemungkinan besar browser akan melakukannya, jadi saya masih berpikir masalah ini valid.

Sunting: Saya pikir mungkin bagian spesifikasi ini yang tampaknya menentukan bahwa resolusi modul 'ditentukan host'?

@kj teks spesifikasi yang relevan ada dalam spesifikasi HTML: https://html.spec.whatwg.org/multipage/webappapis.html#resolve -a-module-specifier

Dikatakan bahwa penentu impor harus berupa URL lengkap atau jalur absolut atau relatif. Jika penentu tidak diuraikan sebagai URL (biasanya dimulai dengan http:// atau https:// ) atau dimulai dengan / , ./ , atau ../ , kesalahan dilemparkan. Penentu jalur diselesaikan berdasarkan URL dasar importir.

Tidak ada pencarian atau resolusi jalur lain yang dilakukan. Ini berarti bahwa penentu harus menyelesaikan ke URL lengkap modul dan Anda harus menyertakan ekstensi jika server memerlukannya. Server memiliki opsi untuk mengembalikan respons untuk URL tanpa ekstensi.

Alasan mengapa Node menggunakan algoritme resolusi yang lebih ketat untuk modul adalah agar lebih kompatibel dengan web, sehingga lebih umum bahwa modul yang diterbitkan ke npm tidak memerlukan alat tambahan untuk berjalan secara native di browser. Mengimpor berdasarkan nama paket masih merupakan fitur yang sangat penting, jadi Node mendukungnya, tetapi bertujuan agar kompatibel dengan proposal Import Maps (yang sudah didukung oleh Deno dan SystemJS).

Semua mengatakan, dukungan tsc untuk mengimpor dengan ekstensi .js berfungsi dengan baik di browser Node dan web. Sebenarnya impor tanpa ekstensi yang menyebabkan masalah tanpa alat tambahan. Biasanya, alat yang mendukung resolusi Node untuk nama paket juga akan menggunakan resolusi gaya kelas require() dan menyelesaikan jalur relatif dan menambahkan ekstensinya juga. Inilah yang dilakukan es-dev-server .

Terima kasih @justinfagnani. Jadi setidaknya di browser itu benar-benar tergantung pada bagaimana server mengimplementasikannya. Itu menyenangkan untuk diketahui. Ini masih cukup tidak intuitif dan membingungkan dan saya yakin perlu ada lebih banyak konvergensi antara proyek untuk kebaikan komunitas, tetapi saya tidak lagi yakin seperti apa bentuknya.

Sunting: Untuk saat ini, ini sudah cukup bagi saya (terutama mengingat penjelasan di atas, saya merasa lebih nyaman dengannya):

https://nodejs.org/api/esm.html#esm_customizing_esm_specifier_resolution_algorithm

Saya tidak yakin apakah opsi ini direferensikan dalam dokumentasi TypeScript, tetapi jika tidak, mungkin itu untuk menghindari kebingungan. Tampaknya tidak, mencari baik ' site:typescriptlang.org specifier-resolution' atau ' site:staging-typescript.org specifier-resolution'. Meskipun, karena ini masih cukup baru di Node, itu tidak terlalu mengejutkan.

@justinfagnani Saya setuju bahwa ekstensi .js hanya berfungsi dalam banyak kasus, kecuali untuk kasus di mana seseorang mengambil sikap ideologis _against_ (misalnya https://github.com/TypeStrong/ts-node/issues/783, yang Anda kenal).

Saya membuat versi bebas ketergantungan dari skrip @quantuminformation di sini . Versi itu juga berisi regex yang hanya akan menggantikan modul yang tidak diakhiri dengan .js .

kebutuhan yang sama

Mencapai ekstensi .js untuk kompatibilitas ESM dengan menggunakan .js dalam pernyataan impor tidak berfungsi untuk saya. Ketika saya mengimpor file TS dan menghilangkan ekstensi apa pun, itu dikompilasi dengan baik. Ketika saya menambahkan ekstensi .js ke impor, saya mendapatkan banyak kesalahan (yang seharusnya tidak ada) dari kompiler TS.

Tampaknya alasan utama mengapa fitur ini tidak dikembangkan adalah karena kesulitan/ketidakmungkinan kompatibilitas dengan berbagai bundler, tetapi Node.js dan bundlers mengembangkan skema modul mereka sendiri tanpa adanya dukungan untuk modul di ECMAScript. Sekarang kami memiliki ESM, yang dianggap tidak memadai oleh sebagian orang, ini adalah jalan ke depan. Karena lebih banyak kode dikembangkan di ESM dan komponen web, penggunaan bundler akan berkurang, dan titik nyeri antara TS dan ESM ini akan mengembangkan lebih banyak gesekan. Akan lebih baik, bahkan jika dukungan awal bermasalah dan tidak mempertimbangkan semua kasus penggunaan, jika itu bisa mulai didukung.

Sampai ada solusi yang lebih baik, ini adalah skrip simpul tanpa ketergantungan untuk digunakan sebagai tugas pembuatan

konfigurasikan di package.json Anda:

  ..
    "scripts": {
        "build": "node build.js",
   ...

//build.js
import { execSync} from "child_process"
import * as util from "util"
import * as fs from "fs"
import * as path from "path"

//function to recurse dirs finding files
function fromDir(startPath, filter, callback) {

    //console.log('Starting from dir '+startPath+'/');

    if (!fs.existsSync(startPath)) {
        console.log("no dir ", startPath);
        return;
    }

    var files = fs.readdirSync(startPath);
    for (var i = 0; i < files.length; i++) {
        var filename = path.join(startPath, files[i]);
        var stat = fs.lstatSync(filename);
        if (stat.isDirectory()) {
            fromDir(filename, filter, callback); //recurse
        }
        else if (filter.test(filename)) callback(filename);
    };
};

//this add .js to lines like:  import .* from "\.  <-- only imports from ./ or ../ are touched
function addDotJsToLocalImports(filename) {
    var buf = fs.readFileSync(filename);
    let replaced = buf.toString().replace(/(import .* from\s+['"])(?!.*\.js['"])(\..*?)(?=['"])/g, '$1$2.js')
    if (replaced !== buf.toString()) {
        fs.writeFileSync(filename, replaced)
        console.log("fixed imports at "+filename )
    }
}

//------------------------
//---BUILD TASK START 
//------------------------

execSync("npx tsc --build -verbose", { stdio: 'inherit' })

//add .js to generated imports so tsconfig.json module:"ES2020" works with node
//see: https://github.com/microsoft/TypeScript/issues/16577
fromDir("./dist", /\.js$/, addDotJsToLocalImports)

berdasarkan https://github.com/microsoft/TypeScript/issues/16577#issuecomment -310426634

Adakah yang bisa mengingat apa yang mereka lakukan 3 tahun yang lalu ketika masalah ini dibuka?

Solusi non-bundler adalah menulis proyek terdistribusi web dengan .js sebagai ekstensi.

Itu 100% berhasil. Masalah yang lebih besar adalah mencoba menulis modul yang menargetkan web dan Node.js, tapi itu masalah untuk JS secara umum.

Jika ada sesuatu yang harus dilakukan, itu akan menambahkan --moduleResolution=web , tapi itu bukan ruang lingkup masalah ini di sini.

Saya harus menulis skrip post-build ini untuk menambahkan ekstensi .js.

fix-ts-imports

#!/usr/bin/env sh

# Fixes JavaScript module imports generated by TypeScript without extension.
# Converts
# import {} from './module'
# into
# import {} from './module.js'
#
# EXAMPLE
# ./fix-ts-imports

ProjectDir="$(cd "$(dirname "$0")/.." && pwd)"

fix() {(
        local pkg="$1"
        shift

        find "$pkg" -type f -iname '*.js' -not -ipath '*/node_modules/*' -print0 \
        | while read -r -d '' file; do
                sed -i '' -E 's|(import .+ from ['\''"]\.?\./.+[^.][^j][^s])(['\''"])|\1.js\2|g' "$file"
        done
)}

if test $# -eq 0; then
        set -- "$ProjectDir"
fi

for pkg; do
        fix "$pkg"
done

Saya memiliki skrip serupa, dalam JavaScript:
https://github.com/yoursunny/NDNTs/blob/743644226fe18d48e599181e87ad571a2708a773/mk/build-post.js

Ini dipanggil sebagai:

tsc -b mk/tsconfig-solution.json -w --listEmittedFiles \
  | node mk/build-post.js

Kelemahan utama dari skrip semacam ini adalah mereka merusak peta sumber, sehingga debugging menjadi kurang efektif.

menggunakan perkakas modern dan ekstensi .js di sumber, semuanya bekerja dengan sangat baik di node dan browser

  • naskah
  • modul es
  • rollup

saya hanya dapat berasumsi bahwa orang-orang yang mengalami masalah di sini sebenarnya terjebak dalam beberapa hibrida es-modul dan resolusi simpul yang rusak, karena pengembang berpegang teguh pada landmark yang sudah dikenal dari alur kerja lama mereka — mungkin webpack yang harus disalahkan...

— mungkin webpack yang harus disalahkan...

Jadi — kucing itu keluar dari tas.

menggunakan perkakas modern dan ekstensi .js di sumber, semuanya bekerja dengan sangat baik di node dan browser

_Kebanyakan_ hal bekerja dengan sangat baik, dan saya setuju bahwa semua file sumber harus memiliki ekstensi .js dalam ekspornya. Dalam pengalaman saya, satu hal yang tidak bekerja dengan baik dengan ini adalah ts-node, karena penolakan keras kepala mereka untuk mendukung .js extensions . Ya, Anda dapat menambahkan langkah pra-transpilasi sebelum menjalankan node, dan impor .js akan berfungsi, tetapi jika Anda ingin menjalankan kode .ts atau menguji langsung dengan node dan juga di browser, Anda saat ini sebagian besar kurang beruntung. (Untuk memperjelas, saya pikir ini adalah bug ts-node, bukan bug TypeScript).

Terima kasih @chase-moskal.

Saya memfaktorkan ulang repo dan file tsconfig, dan sekarang
import {something} from './something.js'
tidak melempar
typescript force overwrite error TS5055: Cannot write file because it would overwrite input file
lagi, dan saya tidak perlu hack fix-ts-imports lagi.

Dalam 250+ komentar, sangat sedikit kejelasan. Untuk meringkas:

Latar belakang

Modul peramban

Browser menyelesaikan modul EcmaScript menurut URL, termasuk URL relatif. ( APA )

Modul Node.js

Node.js menyelesaikan modul (baik EcmaScript dan CommonJS khusus Node.js) melalui algoritme yang jauh lebih kompleks yang melibatkan banyak fallback dan parsing file package.json. ( Node.js ) Itu bisa dikustomisasi, misalnya dengan --experimental-specifier-resolution=explicit yang membutuhkan path lengkap.

Modul TypeScript

TypeScript memiliki beberapa algoritme resolusi modul yang tersedia dan berbagai opsi untuk menyesuaikannya lebih lanjut. ( TypeScript ) Tujuannya adalah agar pengguna menulis penentu modul yang sama seperti yang digunakan dalam output yang dihasilkan, menyesuaikan resolusi tsc dengan opsi seperti baseUrl dan pathMappings.

Dalam praktiknya, sebagian besar pengguna menggunakan node moduleResolution, yang menargetkan lingkungan Node.js atau bundler yang kompatibel. Permintaan ini berfokus pada pengguna yang menargetkan browser tanpa bundler.

resolusi modul ts-node

Rupanya, ts-node tidak mendukung pengidentifikasi modul dengan ekstensi. Meskipun tidak jelas mengapa, karena Node.js dan TypeScript melakukannya, dan ts-node seolah-olah merupakan penggabungan dari keduanya.

Fakta

Fakta 1: Anda dapat menggunakan ekstensi .js

Untuk kompatibilitas yang lebih luas (yaitu browser), Anda dapat menggunakan ekstensi .js hari ini. Dengan pengecualian aneh ts-node (bug IMO), semuanya berfungsi sekarang dengan menentukan path lengkap (yaitu, termasuk ekstensi).

Fakta 2: Ini tidak sesederhana "menambahkan ekstensi"

Permintaan ini lebih baik diringkas sebagai "mengubah pengidentifikasi modul ke jalur file." Misalnya ./example menjadi ./example/index.js dan 'lodash' menjadi '.node_modules/lodash/index.js' .

Perhatikan bahwa terkadang bahkan tidak ada jalur file yang diselesaikan, seperti dengan deklarasi modul ambien.

declare module "lodash" {
}

Mungkin penulisan ulang modul terbatas pada modul TS dalam proyek/kompilasi saat ini.

Bagaimanapun, kami sekarang melanggar salah satu parameter desain TS, bahwa modul lain memengaruhi output untuk yang sekarang.

Kesimpulan

Dimungkinkan untuk menggunakan jalur untuk pengidentifikasi modul yang berfungsi untuk web. (Misalnya ./foo/index.js bukannya ./foo .)

(Meskipun secara praktis, Anda mungkin tetap menginginkan bundler menargetkan browser. Yaitu, jika paket npm digunakan.)

@pauldraper ada masalah penting dengan "Fakta 2":

Permintaan ini lebih baik diringkas sebagai "mengubah pengidentifikasi modul ke jalur file." Misalnya ./example menjadi ./example/index.js dan 'lodash' menjadi 'node_modules/lodash/index.js'.

Anda benar-benar tidak ingin menyelesaikan penentu di luar paket Anda pada waktu kompilasi, karena ini mungkin bukan jalur yang tersedia saat paket diinstal di tempat lain. Anda perlu menjalankan resolusi modul Node di setiap instalasi paket unik. Jika tidak, kita dapat menulis dan menerbitkan import {} from './node_modules/lodash/index.js' dan menyelesaikannya.

@justinfagnani , saya setuju, tetapi itu menunjukkan bahwa pengidentifikasi modul bersifat abstrak dan Anda memanipulasi lokasi modul di luar tsc. Dan tsc itu tidak bisa/tidak perlu menyibukkan diri dengan manipulasi semacam itu.

Permintaan ini lebih baik diringkas sebagai "mengubah pengidentifikasi modul ke jalur file." Misalnya ./example menjadi ./example/index.js dan 'lodash' menjadi '.node_modules/lodash/index.js'.
Perhatikan bahwa terkadang bahkan tidak ada jalur file yang diselesaikan, seperti dengan deklarasi modul ambien.

Itu bukan tentang permintaan ini. Ini tentang menambahkan ekstensi saat memancarkan kode. Kami ingin menulis modul yang kompatibel dengan tipe: "modul" tanpa langkah pembuatan peretasan tambahan. Modul eksternal seperti lodash akan terus bekerja bahkan tanpa .js karena ini adalah CommonJs.

Contoh:

// ./src/moduleA.ts
export const test = 2;
// ./src/moduleB.ts
import {test} from './moduleA'



md5-ec0300a1c6d92a03c70699d0e52c0072



```js
// ./lib/moduleB.js
import {test} from './moduleA.js'

Selain TypeScript di atas tidak mendukung package.json "ekspor" dan "ketik". Tidak ada jalan menuju ESM sejati dalam proyek yang saya kelola.

Permintaan ini berfokus pada pengguna yang menargetkan browser tanpa bundler.

Itu tidak benar. Saya jarang menulis TS/JS untuk browser, saya kebanyakan bekerja pada kode sisi server dan saya juga membutuhkan ini karena saya ingin menggunakan ESM memuat di simpul dan tidak bergantung pada bundler dan kode tambahan untuk memuat modul.

Modul eksternal seperti lodash akan terus bekerja bahkan tanpa .js karena ini adalah CommonJs.

Kecuali mereka tidak.

Saat dipancarkan.

Mungkin ./moduleA.js . Atau mungkin ./moduleA/index.js , kan? Resolusi modul Node.js mengizinkan sejumlah jalur.

Kecuali mereka tidak.

Bisakah Anda memberikan contoh ketika ini tidak berhasil? Node.js baru saja mendapatkan dukungan untuk mengimpor ekspor bernama dari CommonJS.
https://nodejs.org/api/esm.html#esm_import_statements

Mungkin ./moduleA.js. Atau mungkin ./moduleA/index.js, kan? Resolusi modul Node.js mengizinkan sejumlah jalur.

Tidak dalam mode ESM. index.js tidak lagi didukung seperti sekarang. Pemuat ESM akan membaca metadata package.json "ekspor" dan "ketik".
https://nodejs.org/api/esm.html#esm_mandatory_file_extensions

Untuk proyek berbasis TypeScript + node.js, kami membutuhkan cerita ESM asli yang lebih baik. Hal ini dapat terjadi melalui tooling (typescript) atau di node.js Masalahnya adalah kurangnya konsensus tentang apa yang harus dilakukan.

Edit tautan yang dihapus ke simpul PR karena menyesatkan.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat

Masalah terkait

dlaberge picture dlaberge  ·  3Komentar

siddjain picture siddjain  ·  3Komentar

Antony-Jones picture Antony-Jones  ·  3Komentar

kyasbal-1994 picture kyasbal-1994  ·  3Komentar

remojansen picture remojansen  ·  3Komentar