Menu

TypeScript Modülleri: Import, Export ve import type

En üst seviyede bir import ya da export içeren her TypeScript dosyası bir modüldür. Named ve default export'ları, import type ve export type'ı, module ayarının ES modülü ile CommonJS çıktısı arasında nasıl seçim yaptığını ve node16 ile nodenext'in import'larda neden .js uzantısı istediğini öğrenin.

Bu sayfada çalıştırılabilir editörler var - düzenle, çalıştır ve sonucu anında gör.

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çimNeyi 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, type ile 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.
  • .ts dosyalarını doğrudan Node'da çalıştırmak (type stripping) tip işaretlemelerini siler ama diğer dosyalara bakmaz. İşaretlenmemiş bir import { Point } kodda kalır ve Node çalışma zamanında SyntaxError: 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 ad node_modules iç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.json dosyasındaki exports alanında listelenmeyen bir alt yol. node16, nodenext ve bundler çö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 .tsES modülü
Bunu içermeyen bir paketteki .tsCommonJS
.mtsher zaman ES modülü, .mjs olarak üretilir
.ctsher 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" (module değeri esnext, preserve ya da commonjs iken), bundler çözdüğü için uzantısız ./math yolunu kabul eder.
  • rewriteRelativeImportExtensions: true, Node .ts dosyasını doğrudan çalıştırdığında da işleyen ./math.ts yolunu yazmanıza izin verir ve çıktıda onu ./math.js olarak 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.

Coddy programming languages illustration

Coddy ile kodlamayı öğren

BAŞLA