Bir TypeScript modülü, en üst seviyede en az bir import ya da export içeren bir dosyadır. İçinde tanımlanan her şey siz export etmedikçe dosyaya özeldir ve diğer dosyalar ihtiyaç duyduklarını import eder. Söz dizimi, JavaScript'in ES modülü söz dizimi artı birkaç yalnızca tipe özel biçimdir.
Named ve Default Export'lar
Bir projede birçok dosya vardır, bu yüzden import eden taraf şöyle görünür. Default export süslü parantez olmadan import edilir ve herhangi bir ad alabilir; named export'lar süslü parantez içine yazılır ve siz as ile yeniden adlandırmadıkça adlarını korur.
// main.ts
import describe, { distance, ORIGIN, type Point } from "./math.js";
import { distance as dist } from "./math.js"; // renamed on import
import * as math from "./math.js"; // everything, as one object
const p: Point = { x: 6, y: 8 };
console.log(describe(p), distance(ORIGIN, p), dist(p, p), math.ORIGIN);
| Biçim | Neyi import eder |
|---|---|
import { a, b } from "./m.js" | a ve b named export'larını |
import x from "./m.js" | default export'u, x adıyla |
import * as m from "./m.js" | her export'u tutan bir namespace nesnesini |
import { a as b } from "./m.js" | a'yı, bu dosyada b olarak yeniden adlandırılmış şekilde |
import type { T } from "./m.js" | yalnızca tipleri, çıktıdan silinir |
import "./setup.js" | dosyayı yan etkileri için çalıştırır |
export { a } from "./m.js" | a'yı import etmeden yeniden export eder |
export * from "./m.js" | her named export'u yeniden export eder |
Yeniden export'lar, tek bir dosyanın (çoğu zaman index.ts) bir klasörün public API'sini toplamasını sağlar. Canlı bağlamalar ve modül önbelleği gibi düz JavaScript modül davranışları ES modülleri sayfasında anlatılır.
import type ve export type
Tipler çalışma zamanında yoktur, bu yüzden yalnızca tip olarak kullanılan bir import'un yükleyeceği bir şey yoktur. import type bunu açıkça söyler ve ifade JavaScript çıktısından kaybolur. type belirteci, normal bir import içindeki tek bir ad üzerinde de çalışır.
import type { User } from "./models.js"; // whole statement erased
import { saveUser, type Settings } from "./api.js"; // only saveUser survives
export type { User }; // re-export a type only
export type UserId = User["id"];
Anahtar kelime olmadan da TypeScript yalnızca tip olduğunu görebildiği adları çıkarır. İki ayar anahtar kelimeyi zorunlu kılar:
verbatimModuleSyntax: true,typeile işaretlenmemiş her import'u korur; bu yüzden işaretlenmemiş bir tip import'u TS1484 hatasıdır:'Point' is a type and must be imported using a type-only import when 'verbatimModuleSyntax' is enabled..tsdosyalarını doğrudan Node'da çalıştırmak (type stripping) tip işaretlemelerini siler ama diğer dosyalara bakmaz. İşaretlenmemiş birimport { Point }kodda kalır ve Node çalışma zamanındaSyntaxError: The requested module './math.ts' does not provide an export named 'Point'ile başarısız olur.
Her yalnızca tip import'una type yazmak iki durumda da çalışır, bu yüzden edinilmesi gereken alışkanlık budur.
Cannot Find Module
Bir import'taki yol bir dosyaya ya da tipleri olan bir pakete çıkmıyorsa derleyici TS2307 hatasıyla durur. Görmek için bunu çalıştırın:
Çıktı şudur: index.ts(2,29): error TS2307: Cannot find module './utils.js' or its corresponding type declarations. Olağan nedenler:
- Göreli bir yolda yazım hatası ya da eksik bir
./(onsuz adnode_modulesiçinde aranır). - Tiplerini içermeyen bir JavaScript paketi: varsa
@types/{package}paketini kurun ya da onun için bir declaration dosyası yazın. - Paketin
package.jsondosyasındakiexportsalanında listelenmeyen bir alt yol.node16,nodenextvebundlerçözümlemesi altında yalnızca listelenen giriş noktaları import edilebilir.
ES Modülü mü CommonJS Çıktısı mı
Her zaman import ve export yazarsınız. tsconfig.json içindeki module seçeneği hangi JavaScript'in çıkacağına karar verir.
// Source, the same in both cases
import { add } from "./math.js";
console.log(add(1, 2));
// module: nodenext, in a package with "type": "module"
import { add } from "./math.js";
console.log(add(1, 2));
// module: nodenext, in a package without "type": "module"
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const math_js_1 = require("./math.js");
console.log((0, math_js_1.add)(1, 2));
node16, node18, node20 ya da nodenext ile TypeScript her dosya için Node'un kendi kurallarını izler:
| Dosya | Çıktı biçimi |
|---|---|
"type": "module" içeren bir paketteki .ts | ES modülü |
Bunu içermeyen bir paketteki .ts | CommonJS |
.mts | her zaman ES modülü, .mjs olarak üretilir |
.cts | her zaman CommonJS, .cjs olarak üretilir |
module: "esnext" ya da "preserve" ile çıktı import/export ifadelerini korur; Vite ve esbuild gibi bundler'ların beklediği de budur. İki modül sisteminin çalışma zamanındaki farkları CommonJS ve ESM sayfasındadır.
Import'larda Dosya Uzantıları
module: node16 ya da nodenext altında bir ES modülü dosyası, Node'un gerçekten yükleyeceği dosyayı adlandırmak zorundadır ve bu, derlenmiş .js dosyasıdır. TypeScript tip kontrolü için ./math.js yolunu math.ts dosyasına eşler.
import { add } from "./math"; // error TS2835 in an ES module file
import { add } from "./math.js"; // correct: the path as it exists after compiling
Hata metni şudur: Relative import paths need explicit file extensions in ECMAScript imports when '--moduleResolution' is 'node16' or 'nodenext'. Did you mean './math.js'? Aynı ayarlar altındaki CommonJS dosyaları uzantıyı yazmayabilir, çünkü require uzantıları kendisi dener.
İki başka kurulum kuralı değiştirir:
moduleResolution: "bundler"(moduledeğeriesnext,preserveya dacommonjsiken), bundler çözdüğü için uzantısız./mathyolunu kabul eder.rewriteRelativeImportExtensions: true, Node.tsdosyasını doğrudan çalıştırdığında da işleyen./math.tsyolunu yazmanıza izin verir ve çıktıda onu./math.jsolarak yeniden yazar.
Modül Çözümleme ve paths
"zod" gibi çıplak bir ad için TypeScript node_modules içine bakar, paketin package.json dosyasını (exports ve types alanlarını) okur ve son çare olarak node_modules/@types/zod konumuna düşer. Göreli adlar (./, ../) import eden dosyadan itibaren çözülür. Bir .json dosyası da import edilebilir; bunun için gereken ayarlar JSON sayfasındadır.
tsconfig.json içindeki paths, kendi klasörleriniz için takma adlar ekler:
{
"compilerOptions": {
"module": "esnext",
"moduleResolution": "bundler",
"paths": {
"@lib/*": ["./src/lib/*"]
}
}
}
paths yalnızca tip kontrolünü etkiler. Üretilen dosya hâlâ import { v } from "@lib/util" der, bu yüzden çalışma zamanında onu başka bir şeyin çözmesi gerekir: aynı takma adla yapılandırılmış bir bundler ya da package.json içindeki Node imports alanı ("#lib/*": "./dist/lib/*" gibi # ile başlayan takma adlar), ki bu hiçbir ek araç olmadan çalışır. baseUrl TypeScript 7'de kaldırıldı (TS5102 hatası); paths girdilerini tsconfig.json dosyasına göre, başında ./ olacak şekilde yazın.
Sıkça Sorulan Sorular
TypeScript'te import ile import type arasındaki fark nedir?
import type { User } from "./user.js" yalnızca tip getirebilir ve ifadenin tamamı JavaScript çıktısından silinir. Düz bir import hem değer hem tip getirebilir; TypeScript yalnızca tip olarak kullanılan adları çıkarır, ancak verbatimModuleSyntax açıkken çıktının tam olarak yazdığınız gibi olması için bunları type ile işaretlemenizi ister.
TypeScript import yollarında neden .js istiyor?
module: node16 ya da nodenext altında bir ES modülü dosyası, Node'un çalışma zamanında yükleyeceği gerçek dosya adıyla import etmek zorundadır ve bu dosya derlenmiş .js dosyasıdır. TypeScript tip kontrolü sırasında ./math.js yolunu math.ts dosyasına çözer. Bir ES modülü dosyasında uzantıyı yazmamak TS2835 hatasıdır.
TypeScript'te export default mu yoksa named export mu kullanmalıyım?
İkisi de çalışır. Birçok ekip named export'ları tercih eder: ad, onu import eden her dosyada aynıdır, editörler onları güvenilir şekilde otomatik import eder ve yeniden adlandırmak bir arama değil bir refactor işlemidir. Default export ise her import edenin kendi adını seçmesine izin verir.
tsconfig'deki paths seçeneği çıktıdaki import'u değiştirir mi?
Hayır. paths yalnızca tip denetleyicisine bir modülü nerede bulacağını söyler. Üretilen JavaScript "@lib/util" yolunu yazıldığı gibi korur, bu yüzden çalışma zamanında onu bir bundler'ın ya da package.json içindeki Node imports alanının çözmesi gerekir.
TypeScript'te "Cannot find module" hatasını nasıl düzeltirim?
TS2307 hatası, yolun TypeScript'in bulabileceği bir dosyayı göstermediği ya da bir paketin tip içermediği anlamına gelir. Göreli yolu ve uzantıyı kontrol edin, paketin yerleşik tipleri yoksa @types/... paketini kurun ya da onun için küçük bir declaration dosyası yazın.