当前位置: 首页 > news >正文

TypeScript中的import语法详解

1 TypeScript模块系统概述

1.1 什么是模块化开发

模块化开发是现代前端开发的核心概念之一。它将复杂的代码拆分成独立的、可重用的模块,每个模块都有明确的职责和接口。

// user.service.ts - 一个简单的用户服务模块
export class UserService {getUsers(): Promise<User[]> {return fetch('/api/users').then(res => res.json());}getUserById(id: number): Promise<User> {return fetch(`/api/users/${id}`).then(res => res.json());}
}export interface User {id: number;name: string;email: string;
}

模块化的好处包括:

  • 可维护性:代码结构清晰,易于维护
  • 可重用性:模块可以在不同项目中重复使用
  • 依赖管理:明确模块间的依赖关系
  • 作用域隔离:避免全局变量污染

1.2 TypeScript模块系统的特点

TypeScript完全兼容ES6模块系统,并在此基础上增加了类型检查和更丰富的功能。

// math.utils.ts
export const PI = 3.14159;export function add(a: number, b: number): number {return a + b;
}export function multiply(a: number, b: number): number {return a * b;
}// 默认导出
export default class Calculator {calculate(operation: 'add' | 'multiply', a: number, b: number): number {switch(operation) {case 'add': return add(a, b);case 'multiply': return multiply(a, b);default: throw new Error('Unsupported operation');}}
}

TypeScript模块系统的主要特点:

  1. 静态分析:编译时就能确定模块依赖关系
  2. 类型安全:导入导出都有完整的类型检查
  3. 工具支持:IDE可以提供智能提示和自动导入
  4. Tree Shaking:未使用的代码可以被构建工具移除

1.3 模块与命名空间的区别

在TypeScript早期版本中,命名空间(namespace)是组织代码的主要方式,但现在推荐使用模块。

// 使用命名空间(不推荐)
namespace Validation {export interface StringValidator {isAcceptable(s: string): boolean;}const lettersRegexp = /^[A-Za-z]+$/;export class LettersOnlyValidator implements StringValidator {isAcceptable(s: string) {return lettersRegexp.test(s);}}
}// 使用模块(推荐)
// validation.ts
export interface StringValidator {isAcceptable(s: string): boolean;
}const lettersRegexp = /^[A-Za-z]+$/;export class LettersOnlyValidator implements StringValidator {isAcceptable(s: string): boolean {return lettersRegexp.test(s);}
}

模块与命名空间的主要区别:

特性 模块 命名空间
作用域 文件级别 全局级别
加载方式 按需加载 全部加载
依赖管理 明确声明 隐式依赖
构建优化 支持Tree Shaking 不支持

2 import语法基础

2.1 import语句的基本概念

import语句用于从其他模块中引入变量、函数、类或其他可导出的值。它是ES6模块系统的核心语法之一。

// 基本语法结构
// import [导入声明] from '[模块路径]';// 从math.utils.ts模块导入
import Calculator, { PI, add, multiply } from './math.utils';
import { PI as PI_CONSTANT } from './math.utils'; // 重命名导入
import * as MathUtils from './math.utils'; // 命名空间导入
import './side-effect-module'; // 仅导入副作用

2.2 默认导入(Default Import)

每个模块可以有一个默认导出,使用默认导入时不需要花括号。

// logger.ts
export default class Logger {log(message: string): void {console.log(`[LOG] ${message}`);}error(message: string): void {console.error(`[ERROR] ${message}`);}
}// config.ts
const config = {apiUrl: 'https://api.example.com',timeout: 5000
};export default config;// app.ts - 使用默认导入
import Logger from './logger'; // 导入默认类
import config from './config'; // 导入默认对象const logger = new Logger();
logger.log('Application started');console.log(`API URL: ${config.apiUrl}`);

默认导入的特点:

  • 每个模块只能有一个默认导出
  • 导入时可以使用任意名称
  • 不需要使用花括号

2.3 命名导入(Named Import)

命名导入用于导入模块中通过export关键字导出的特定成员。

// api-client.ts
export interface ApiResponse<T> {data: T;status: number;message: string;
}export class ApiClient {async get<T>(url: string): Promise<ApiResponse<T>> {const response = await fetch(url);return {data: await response.json(),status: response.status,message: response.statusText};}
}export const API_BASE_URL = 'https://api.example.com';
export const DEFAULT_TIMEOUT = 5000;// constants.ts
export const APP_NAME = 'My Application';
export const VERSION = '1.0.0';
export const AUTHOR = 'TypeScript Developer';// main.ts - 使用命名导入
import { ApiClient, API_BASE_URL } from './api-client';
import { APP_NAME, VERSION, AUTHOR } from './constants';
import { ApiResponse } from './api-client'; // 只导入类型console.log(`${APP_NAME} v${VERSION} by ${AUTHOR}`);
const client = new ApiClient();

命名导入的特点:

  • 可以导入多个特定成员
  • 名称必须与导出时一致(除非重命名)
  • 必须使用花括号包围

2.4 通配符导入(Namespace Import)

通配符导入将整个模块作为命名空间对象导入,可以访问模块的所有导出成员。

// utilities.ts
export function formatDate(date: Date): string {return date.toISOString().split('T')[0];
}export function formatCurrency(amount: number): string {return `$${amount.toFixed(2)}`;
}export function capitalize(str: string): string {return str.charAt(0).toUpperCase() + str.slice(1);
}export const DEFAULT_DATE_FORMAT = 'YYYY-MM-DD';
export const CURRENCY_SYMBOL = '$';// app.ts - 使用通配符导入
import * as utils from './utilities';console.log(utils.formatDate(new Date())); // 2023-12-07
console.log(utils.formatCurrency(123.45)); // $123.45
console.log(utils.capitalize('hello')); // Hello
console.log(utils.CURRENCY_SYMBOL); // $

通配符导入的使用场景:

  • 需要使用模块中的多个成员
  • 想要保持模块成员的命名空间组织
  • 导入工具库的所有功能

2.5 无导入的副作用导入

有时我们只需要模块的副作用(如执行初始化代码),而不需要导入任何值。

// polyfills.ts - 填充库,只为了执行副作用
if (!Array.prototype.includes) {Array.prototype.includes = function(searchElement: any): boolean {return this.indexOf(searchElement) !== -1;};
}if (!String.prototype.padStart) {String.prototype.padStart = function(length: number, padString: string = ' '): string {return padString.repeat(Math.max(0, length - this.length)) + this;};
}console.log('Polyfills loaded');// styles.css.ts - CSS导入,只为了应用样式
import './global-styles.css';
import './theme.css';// main.ts - 导入副作用模块
import './polyfills'; // 执行polyfills
import './styles.css'; // 应用样式

这种导入方式常用于:

  • 应用全局样式
  • 执行初始化代码
  • 注册全局事件监听器

3 高级import用法

3.1 混合导入模式

当模块同时有默认导出和命名导出时,可以使用混合导入模式。

// data-service.ts
export interface DataItem {id: number;name: string;
}export function processData(items: DataItem[]): DataItem[] {return items.map(item => ({ ...item, processed: true }));
}export function validateData(items: DataItem[]): boolean {return items.every(item => item.id > 0 && item.name.length > 0);
}// 默认导出
export default class DataService {private data: DataItem[] = [];add(item: DataItem): void {this.data.push(item);}getAll(): DataItem[] {return [...this.data];}
}// app.ts - 混合导入
import DataService, { DataItem, processData, validateData 
} from './data-service';const service = new DataService();
const items: DataItem[] = [{ id: 1, name: 'Item 1' },{ id: 2, name: 'Item 2' }
];if (validateData(items)) {const processed = processData(items);processed.forEach(item => service.add(item));
}

混合导入的语法要点:

  • 默认导出在前,命名导出在后
  • 用逗号分隔默认导入和命名导入
  • 默认导入不需要花括号,命名导入需要

3.2 导入重命名技巧

为了避免命名冲突或提高代码可读性,可以使用导入重命名。

// user-api.ts
export interface User {id: number;name: string;email: string;
}export async function getUser(id: number): Promise<User> {// 模拟API调用return { id, name: `User ${id}`, email: `user${id}@example.com` };
}// product-api.ts
export interface User { // 与user-api.ts中的User同名userId: number;username: string;emailAddress: string;
}export async function getProduct(id: number): Promise<any> {// 模拟API调用return { id, name: `Product ${id}` };
}// order-api.ts
export interface User { // 又一个User接口user_id: number;user_name: string;user_email: string;
}export async function getOrder(id: number): Promise<any> {// 模拟API调用return { id, orderId: `ORDER-${id}` };
}// app.ts - 使用重命名避免冲突
import { User as ApiUser } from './user-api';
import { User as ProductUser } from './product-api';
import { User as OrderUser } from './order-api';import { getUser as fetchUser } from './user-api';
import { getProduct as fetchProduct } from './product-api';// 现在可以清晰地区分不同的User类型
const apiUser: ApiUser = { id: 1, name: 'John', email: 'john@example.com' };
const productUser: ProductUser = { userId: 1, username: 'John', emailAddress: 'john@example.com' };
const orderUser: OrderUser = { user_id: 1, user_name: 'John', user_email: 'john@example.com' };// 使用重命名的函数
fetchUser(1).then(user => console.log(user));
fetchProduct(1).then(product => console.log(product));

重命名的其他用途:

// 使用更语义化的名称
import { createConnection as connectToDatabase } from './database';
import { format as formatDate } from 'date-fns';
import { get as lodashGet } from 'lodash';// 避免与本地变量冲突
const lodashGet = (obj: any, path: string) => obj[path];
import { get as _get } from 'lodash'; // 重命名避免冲突

3.3 动态导入(Dynamic Import)

动态导入允许在运行时按需加载模块,这对于代码分割和懒加载非常有用。

// heavy-module.ts - 假设这是一个大型模块
export class HeavyComputation {performComplexCalculation(data: number[]): number {// 模拟复杂计算return data.reduce((sum, num) => sum + Math.pow(num, 2), 0);
http://www.dtcms.com/a/335770.html

相关文章:

  • 6.Ansible自动化之-管理变量和事实
  • 关于第一次接触Linux TCP/IP网络相关项目
  • 牛客周赛 Round 105
  • Java -- 坐标体系--绘图方法
  • 《详解 C++ Date 类的设计与实现:从运算符重载到功能测试》
  • Originality AI:原创度和AI内容检测工具
  • thingsboard 服务器在2核CPU、2G内存资源配置下如何调优提速,适合开发/演示
  • 飞算JavaAI赋能高吞吐服务器模拟:从0到百万级QPS的“流量洪峰”征服之旅
  • C#读取文件, IO 类属性及使用示例
  • [GLM-4.5] GLM-4.5模型 | Claude Code服务集成
  • Qt 5.5 的安装与配置(使用 VSCode编辑)
  • React 基础实战:从组件到案例全解析
  • Talk2BEV论文速读
  • 什么叫作数据处理?数据处理和数据治理是什么关系
  • Java StringBuffer使用详解
  • Spring MVC 九大组件源码深度剖析(四):HandlerMapping - 请求映射的玄机
  • 电力设备状态监测与健康管理:基于多源异构数据融合的技术实现
  • 【龙泽科技】汽车车身测量与结构件更换仿真教学软件【GEELY+CHIEF】
  • Wasserstein GAN:如何解决GANS训练崩溃,深入浅出数学原理级讲解WGAN与WGAN-GP
  • (机器学习)监督学习 vs 非监督学习
  • 机器学习05-朴素贝叶斯算法
  • Elasticsearch 在向量捜索中使用 Direct I0
  • java-maven
  • 佳文赏读 || (CVPR 2025新突破) Robobrain:机器人操作从抽象到具体的统一大脑模型(A Unified Brain Model)
  • 【教程】笔记本安装FnOS设置合盖息屏不休眠
  • Pulsar存储计算分离架构设计之存储层BookKeeper(上)
  • Android 组件封装实践:从解耦到架构演进
  • JavaWeb前端(HTML,CSS具体案例)
  • 【基础】贪心 区间覆盖
  • GANs生成对抗网络生成手写数字的Pytorch实现