Typescript: impor paksa

Dibuat pada 4 Sep 2014  ·  31Komentar  ·  Sumber: microsoft/TypeScript

Saya memiliki banyak skenario di mana saya akan melakukan ini:

import myExternalModule = require("./myExternalModule");
// not using myExternalModule here

Saya tidak menggunakan myExternalModule dalam kode saya, tetapi saya tetap ingin menyertakannya menggunakan requirejs. Saya hanya perlu berada di sana.
Jika mungkin ada kata kunci forceimport itu akan sangat keren!

Question

Komentar yang paling membantu

jadi mengapa tidak menambahkan saja

import * as React from "react"; // get the types
import "react";  // just for side effect

dalam keluaran, impor terakhir: import "react" tidak akan dihilangkan.

Semua 31 komentar

Ini harus memungkinkan untuk memaksa emisi dengan menulis

var myExternalModule = require("./myExternalModule");

tetapi ini tidak akan mengeluh jika "./myExternalModule" adalah jalur yang salah.

Pendekatan yang benar adalah dengan memperkenalkan referensi palsu yang tidak memiliki efek samping:

import myExternalModule = require("./myExternalModule"); 
myExternalModule;

Meskipun ini adalah peretasan, sangat tidak mungkin sintaks baru akan diperkenalkan untuk kasus penggunaan yang agak sempit ini. Lihat tujuan desain.

Jika naskah akan memverifikasi jalan di var myExternalModule = require("./myExternalModule"); maka itu akan mengizinkan pengguna untuk memaksa memancarkan _and _ verifikasi get saat kompilasi, tanpa harus resor untuk hack.

Pendekatan var tidak mengimpor tipe dari modul.

Selain itu, Anda dapat menggunakan atribut amd-dependency jika perlu.

Untuk tujuan apa Anda mengimpor barang-barang yang tidak digunakan?

Misalnya di aplikasi sudut saya memiliki beberapa arahan di file lain. Saya perlu mengimpor arahan tersebut atau markup html saya tidak akan berfungsi. Saya tidak menggunakannya dalam JavaScript.
Biasanya dalam sudut, sebagian besar modul dipisahkan dan tidak memiliki ketergantungan satu sama lain, tetapi perlu diimpor agar seluruh aplikasi berfungsi.

: +1:
Itu membuatku bingung.
Mengapa compiler TypeScript menghilangkannya?
modul eksternal bukanlah modul non-instantiated.
membutuhkan memiliki efek samping.
klausul impor tampaknya kompatibel dengan kebutuhan AMD dan CommonJS. tapi sebenarnya tidak.

Masalah ini juga mengganggu ketika modul-modul require () - ing tidak benar-benar mengekspor apa pun melainkan fungsionalitas shim pada objek global, seperti es5-shim , es6-shim dan banyak lagi lainnya.

Itu membuatku bingung.
Mengapa compiler TypeScript menghilangkannya?

Ini adalah pengoptimalan karena terkadang kami hanya ingin mengimpor informasi jenis dari modul:

import foo = require('foo');

function bar(paramOne: foo.ParamOne, paramTwo: foo.ParamTwo){}

ini bukan hanya pengoptimalan. Jika Anda menggunakan modul yang diimpor untuk tipe saja (yaitu tidak digunakan dalam posisi nilai apa pun), kami tidak dapat mengeluarkan logika require untuk itu, karena modul tersebut dapat berupa modul khusus tipe ambien yang tidak ada pada waktu proses. Memancarkan impor modul berarti kesalahan waktu proses mencoba memuat modul yang tidak ada.

Anda dapat menggunakan bendera amd-dependency untuk ini:

/// <amd-dependency path="foo" />

import x = require('foo');

Alih-alih <amd-dependency> yang terlihat seperti sedikit hack, akan lebih menarik untuk menggunakan <reference name="..."> IMO.

@danquirk Adalah hal yang sewenang-wenang dan berbahaya jika mesin TypeScript mengambil tanggung jawab untuk mengoptimalkan pernyataan import. Ada banyak pola yang belum ditangkap TypeScript dari JavaScript. Salah satu contohnya adalah bagaimana ini tidak menunjukkan bahwa this bisa memiliki tipe # 229.

Impor digunakan untuk memuat dependensi sebelum kode saat ini dimuat dan mungkin tidak direferensikan secara langsung. Dependensi sudut adalah salah satu contohnya, sedangkan plugin jQuery adalah contoh lainnya. Pustaka apa pun yang memperluas objek dasar dan tidak direferensikan secara langsung dipengaruhi oleh "fitur". Dengan memutuskan untuk secara sewenang-wenang tidak menyertakan impor berdasarkan analisis statis lokal, Anda menerapkan pola kompilator gaya C atas maksud eksplisit pengembang yang menulis pernyataan impor. Harapan dari impor tulisan adalah bahwa itu akan dimasukkan sebagai ketergantungan dan tersedia untuk lingkup lokal modul. Tindakan lain adalah efek samping dari ekspektasi alami memilih untuk menulis import di dalam modul.

Sangat mungkin bahwa dalam kasus ini compiler TypeScript dapat melakukan lebih sedikit, dan mencapai lebih banyak.

Rilis TypeScript berikutnya akan mendukung modul gaya ES6 (perubahan saat ini ada di master). jadi jika semua yang Anda inginkan adalah mendeklarasikan ketergantungan, Anda dapat menggunakan:

import "myLib";

Kompilator tidak akan mengabaikan impor ini.

Akankah perilaku tidak konsisten yang ada ditangani, atau tetap sebagai sesuatu yang menyenangkan untuk ditemukan orang? Haruskah ditambahkan ke dokumentasi bahwa mereka adalah kasus di mana import tidak menambahkan file sebagai ketergantungan? Ketika membangun modul TypeScript AMD, akankah ///<reference... sekarang dianggap sebagai kesalahan?

Cara kerja import saat ini adalah desain yang buruk. Desain yang buruk menciptakan ambiguitas. Jika perilaku tambahan tidak didefinisikan dengan jelas maka kemungkinan besar akan ditemukan meskipun itu efek samping. Karenanya OP, saya, dan komentar serta bug lain yang terkait dengannya di forum ini.

Ada badan praktik yang sudah ada saat menggunakan manajemen ketergantungan gaya Umum atau Memerlukan. Implementasi import menunjukkan bahwa itu diabaikan.

Mengenai dokumentasi, lihat spesifikasi bagian 11.2.5 dan bagian 11.2.6 :

Deklarasi impor eksternal direpresentasikan dalam JavaScript yang dihasilkan sebagai variabel yang diinisialisasi oleh panggilan ke fungsi 'require' yang disediakan oleh host sistem modul. Deklarasi variabel dan panggilan 'require' dikeluarkan untuk modul impor tertentu hanya jika modul yang diimpor, atau alias lokal (bagian 10.3) yang mereferensikan modul yang diimpor, _ direferensikan sebagai PrimaryExpression di suatu tempat di badan modul pengimporan. Jika modul yang diimpor direferensikan hanya sebagai ModuleName atau TypeQueryExpression, tidak ada yang dikirim_.

Referensi /// tidak sama dengan impor. Referensi /// membawa deklarasi tambahan ke dalam cakupan global Anda, misalnya dom API. itu adalah pernyataan kepada kompilator untuk mempercayai keberadaan entitas ini, dan itu tidak berdampak pada kode yang dihasilkan.

Impor di sisi lain perlu dikeluarkan sebagai pernyataan yang dibutuhkan. dalam kasus Anda hanya menggunakan impor dalam posisi tipe, maksudnya tidak jelas, baik Anda hanya menginginkan tipe (yang merupakan konstruksi waktu desain yang tidak ada pada waktu proses), dan dalam kasus ini Anda ingin impor dihilangkan , dan jika tidak, Anda mungkin akan mengimpor modul hanya tipe yang tidak ada. Atau Anda juga menginginkan efek sampingnya. Untuk yang terakhir, sintaks import "mod"; tampaknya merupakan sintaks yang lebih jelas untuk mendeklarasikan maksud.

@mhegazy Saya tidak ingin membuka edisi baru, tapi ini sedikit masalah di dunia React.
Pertimbangkan kode di bawah ini, ketika dikompilasi ke js referensi React dihapus karena tidak muncul dalam kode dan kode akan gagal karena ReactRouter bergantung padanya. Cara mengatasinya ... benar-benar bodoh ada di bawah kode. Apakah ada cara yang lebih cerdas untuk mengatasi hal itu? Terima kasih.

import * as React from "react"; var temp = React.DOM;
....

// mf("route.schedules", "") // this is to register a translation
anonymousRoutes.route("/schedules", {
  name: "schedules",
  subscriptions: function() {
    this.register("schedules", subscriptions.subscribe("schedules"));
  },
  action: () => {
    ReactLayout.render(ClearLayout, {content: <Book />});
  }
});

MEMPERBAIKI;) - EHM

import * as React from "react"; var temp = React.DOM;
...

kode akan gagal karena ReactRouter bergantung padanya.

apakah perlu var "React" atau hanya beberapa efek samping dari impor?

Ini membutuhkan efek samping dari impor. Variabel ditambahkan hanya untuk tidak menghapus impor dalam kode transparan.

jadi mengapa tidak menambahkan saja

import * as React from "react"; // get the types
import "react";  // just for side effect

dalam keluaran, impor terakhir: import "react" tidak akan dihilangkan.

Sayangnya ini tidak berfungsi dan saya masih mendapatkan:

ReferenceError: React is not defined
    at action [as _action] (schedule_router.jsx:15)
    at Route.callAction (kadira_flow-router.js?f961d732ed2b89a53d490af5979b899800aa1a5d:2306)
    at kadira_flow-router.js?f961d732ed2b89a53d490af5979b899800aa1a5d:2025
    at Object.Tracker.nonreactive (tracker.js:560)
    at kadira_flow-router.js?f961d732ed2b89a53d490af5979b899800aa1a5d:2016
    at Tracker.Computation._compute (tracker.js:294)
    at Tracker.Computation._recompute (tracker.js:313)
    at Object.Tracker._runFlush (tracker.js:452)
    at Object.Tracker.flush (tracker.js:412)
    at Router._invalidateTracker (kadira_flow-router.js?f961d732ed2b89a53d490af5979b899800aa1a5d:2065)

Saya pikir alasannya di sini adalah "dependensi yang lemah" di Meteor, yang bergantung pada _callee_ untuk menyediakan semua referensi yang diperlukan bagi mereka.

Saya mulai mempelajari skrip ketikan baru-baru ini untuk Angular 2. Ini telah menarik perhatian saya beberapa kali seperti yang saya yakin akan terjadi pada pendatang baru lainnya. Saya mengerti bahwa ini adalah pengoptimalan tetapi sebenarnya sangat membingungkan. Jika saya mengetik sesuatu di file ts saya, saya berharap itu menghasilkan, output atau semacamnya tidak mengabaikannya begitu saja. Saya mengerti bahwa saya dapat memaksa pernyataan require untuk diproduksi tetapi itu tampaknya sedikit hacky. Sepertinya ini adalah alasan di mana saya sebagai pengguna harus dapat membuat keputusan sendiri tanpa kompilator memutuskan apa yang terbaik.

TypeScript menghamparkan deklarasi tipe di atas nilai, sehingga sintaks impor yang sama memberi Anda tipe, nilai, atau keduanya. ini membuatnya sangat nyaman dan intuitif untuk bekerja dengan modul; jika Anda memerlukan tipe dari modul lain, cukup impor saat Anda mengimpor variabel, atau cukup impor kelas, dan gunakan keduanya sebagai tipe dan sebagai konstruktor dengan new.

Sisi lain dari ini, Anda dapat memiliki impor ke modul yang tidak ada, karena mereka hanya tipe kontainer. jika kompilator memancarkan referensi ke modul-modul ini, itu akan gagal pada saat run-time. solusi yang kami miliki adalah mendeteksi _ bagaimana_ impor itu digunakan, dan _all_ referensi untuk itu digunakan sebagai tipe, kemudian tidak diperlukan pada saat run-time dan elided.

jelas ini bisa membingungkan jika Anda membutuhkan efek samping dari sebuah modul juga. tetapi sebaliknya juga membingungkan jika impor ke modul yang tidak ada dikeluarkan, biarkan pihak harus kehilangan kenyamanan memaketkan jenis dan nilai bersama dalam sintaks yang sama.

Solusi:
Jika menggunakan resolusi tradisional ( moduleResolution tidak disetel ke node ), pernyataan import yang berisi ! dalam pengenalnya tidak akan pernah bisa dihindari. Saya yakin ini ada hubungannya dengan kami yang mencoba mendukung perilaku systemjs lebih baik, tetapi dapat digunakan untuk memaksa impor. Jika Anda _are_ menggunakan systemjs, requirejs, atau pemuat apa pun yang memungkinkan pemetaan ulang pengenal modul, Anda dapat mengakhiri impor paksa Anda dengan !js atau tanda serupa dan memetakannya dengan pemuat modul Anda. TS akan memancarkan impor kata demi kata (dan tidak mencoba untuk memeriksa atau menyelesaikannya), dan pemuat Anda dapat diajari cara memahami pengimporan.

Tampaknya tim sudah harus membuat kode kasus khusus untuk jenis impor ini seperti di checker.ts:

// If we're compiling under --jsx react, the symbol 'React' should
// be marked as 'used' so we don't incorrectly elide its import. And if there
// is no 'React' symbol in scope, we should issue an error.
if (compilerOptions.jsx === JsxEmit.React) {
    let reactSym = resolveName(node.tagName, "React", SymbolFlags.Value, Diagnostics.Cannot_find_name_0, "React");
    if (reactSym) {
        getSymbolLinks(reactSym).referenced = true;
    }
}

Seperti yang ditunjukkan @mhegazy, ini bukan hanya tentang pengoptimalan tetapi juga untuk menghindari perlunya impor tanpa definisi runtime (misalnya, Antarmuka) yang akan menyebabkan kesalahan waktu proses.

Saya mempertanyakan mana yang akan lebih sering terjadi. Anda dapat dengan mudah mendeteksi apakah impor itu * .d.ts sehingga itu akan mudah dihilangkan.

Dalam kasus lainnya, tampaknya hal yang cukup sepele bagi kompilator untuk mendeteksi bahwa modul yang diimpor tidak akan memiliki keluaran waktu proses dan hanya mengabaikan impor tersebut.

Dari perspektif KERING , saran ini membuat saya berharap saya memiliki transpiler untuk transpiler Anda untuk menulis kode duplikat ini untuk saya.

import * as React from "react"; // get the types
import "react";  // just for side effect

Cara saya melihatnya, itu harus menjadi pilihan file _imported_ apakah perlu dimuat saat runtime (karena tahu itu memiliki efek samping). Ini sebenarnya tidak boleh diputuskan oleh file _loading_ (yaitu, file dengan pernyataan import), karena bukan urusannya untuk mengetahui detail implementasi dari file / modul lain.

Setidaknya ini akan bekerja dengan baik dari sudut pandang angularjs, di mana file yang mendefinisikan direktif dan layanan "tahu" bahwa itu harus dimuat saat runtime jika direferensikan, jadi kompilator tidak boleh mengelilinginya. Beberapa jenis petunjuk dalam file ke compiler skrip untuk "tidak elide" akan memperbaiki IMO ini. Tapi saya mungkin mengabaikan beberapa kasus penggunaan di sini.

-JM

xmodule.ts:

console.log('ive been imported');
export class X {
}
import {X} from "xmodule"; // get the types
import "xmodule";  // just for side effect

Jika xmodule memiliki pernyataan, .eg pernyataan console.log, itu menurut definisi bukan hanya tumpukan deklarasi. Modul pengimpor seharusnya tidak bertanggung jawab untuk membuat pernyataan yang menggunakan xmodule agar xmodule dianggap lebih dari sekadar serangkaian deklarasi tipe.

@wes_keluarga

Anda menyebutkan menggunakan ledakan untuk memaksa impor Anda. Itu lebih disukai untuk skenario saya. Bagaimana cara saya menggunakannya? Mencoba semua hal berikut:

!import {Service} from './service';
import! {Service} from './service';
import {!Service} from './service';
import {Service!} from './service';
import {Service} from '!./service';
import {Service} from './service!';
import {Service} from !'./service';
import {Service} from './service'!;

Itu ada di dalam string - tapi saya pikir perilakunya telah dihapus baru-baru ini ketika pemetaan jalur diperkenalkan.

Saya menggunakan perpustakaan, seperti react, untuk mengimpor node wrapper - h (in react itu react () jika saya tidak salah), jadi saya mengimpor seperti ini:

import { h, Component } from "preact";

Kemudian, tentu saja, saya tidak memiliki jam dalam waktu proses. Karena kenapa harus ada di sana? Juga, menggunakan dengan jsx pertahankan, jadi TypeScript benar-benar tidak tentang h, tetapi kemudian babel tahu.

Jadi, apa yang tersisa, menggunakan referensi seperti h; setelah impor, ya?

Untuk h (atau pabrik jsx kustom lainnya) gunakan --jsxFactory agar kompilator tahu bahwa ini adalah pabrik yang Anda gunakan saat runtime. misalnya --jsxFactory h .

Bukan ini membutuhkan typescript@next saat ini, seharusnya tersedia di TypeScript 2.1.2.

@mhegazy Untuk project yang memiliki dua jenis konsumen BEJ (seperti react dan snabbdom), ini tidak dapat diterima.

Saya sedang mengerjakan proyek yang menggunakan react untuk merender UI web dan dom virtual yang disesuaikan yang diimplementasikan sendiri untuk merender objek webgl. Dan itu menyentuh kasus sudut, karena kita MEMBUTUHKAN dua jenis anotasi @jsx untuk proyek yang sama.

Sekarang saya terpaksa mengekspor h kita sendiri sebagai variabel global ... Itu jelek.

Sertakan saya dalam daftar pengembang yang membutuhkan / menginginkan impor satu liner yang melakukan ini. Dua baris sumber untuk mencapainya adalah apa yang kami coba hilangkan, terutama ketika kami ingin mengimpor banyak modul secara berurutan. Saya rasa apa yang terdengar paling baik bagi saya sejauh ini adalah kata kunci / sintaks untuk memaksa impor. Terima kasih lagi guys!

Apakah halaman ini membantu?
0 / 5 - 0 peringkat