TypeScript学习:TypeScript从入门到精通
蓝桥杯真题解析:蓝桥杯Web国赛真题解析
个人简介:即将大三的学生,热爱前端,热爱生活
你的一键三连是我更新的最大动力❤️!
最近博主一直在创作
TypeScript
的内容,所有的TypeScript
文章都在我的TypeScript从入门到精通专栏里,每一篇文章都是精心打磨的优质好文,并且非常的全面和细致,期待你的订阅❤️
本篇文章将深入去讲解TypeScript
中的模块化,这也许会是你看过的最全面最细致的TypeScript
教程,点赞关注收藏不迷路!
在TypeScript
中,就像在EC5
中一样,任何包含顶级import
或export
的文件都被认为是一个模块
相反的,一个没有任何顶级导入或导出声明的文件被视为一个脚本,其内容可在全局范围内使用(因此也可用于模块)
模块在自己的范围内执行,而不是在全局范围内。这意味着在模块中声明的变量、函数、类等在模块外是不可见的,除非它们被明确地用某种导出形式导出。相反,要使用从不同模块导出的变量、函数、类、接口等,必须使用导入的形式将其导入。
JavaScript
规范声明,任何没有export
或顶层await
的JavaScript
文件都应该被认为是一个脚本而不是一个模块
如果你有一个目前没有任何导入或导出的文件,但你希望它被当作一个模块来处理,可以添加这一行:
export {};
这将改变该文件,使其成为一个什么都不输出的模块。无论你的模块目标是什么,这个语法都有效
TypeScript
中能够使用JavaScript
的模块化语法,并在此基础上提供了一些额外的语法
一个文件可以通过export default
声明一个主要出口:
// @filename: hello.ts
export default function helloWorld() {
console.log("Hello, world!");
}
一个文件中
export default
只能有一个
通过import
导入:
// @filename: a.ts(与 hello.ts同级)
import hello from "./hello";
hello();
import
引入export default
导出的内容时可以自定义导入名称,如上面导出的函数名为helloWorld
,但引入时我们自定义了hello
的名称
除了默认的导出,还可以通过省略default
的export
,导出多个变量和函数的:
// @filename: hello.ts
export var a = 3.14;
export let b = 1.41;
export const c = 1.61;
export class D {}
export function fn(num: number) {
console.log(num);
}
可以只使用一个export
导出:
var a = 3.14;
let b = 1.41;
const c = 1.61;
class D {}
function fn(num: number) {
console.log(num);
}
export { a, b, c, D, fn };
通过import
和{}
实现按需导入:
// @filename: a.ts(与 hello.ts同级)
import { a, b, c, D, fn } from "./hello";
console.log(a, b, c, new D());
fn(1);
可以使用 import {old as new}
这样的格式来重命名一个导入:
// @filename: a.ts(与 hello.ts同级)
// 仅引入a,c,fn 并重命名a和fn
import { a as A, c, fn as FN } from "./hello";
console.log(A, c);
FN(1);
可以把所有导出的对象,用* as name
,把它们放到同一个命名空间name
:
// @filename: a.ts(与 hello.ts同级)
// export导出的所有内容放到了命名空间 F 中
import * as F from "./hello";
console.log(F.a, F.c);
F.fn(1);
export default
与export
一起使用:
// @filename: hello.ts
export var a = 3.14;
export let b = 1.41;
export const c = 1.61;
export class D {}
export function fn(num: number) {
console.log(num);
}
export default function helloWorld() {
console.log("Hello, world!");
}
// @filename: a.ts(与 hello.ts同级)
import hello, { a, b, c, D, fn } from "./hello";
console.log(a, b, c, new D());
fn(1);
hello();
直接导入一个文件
通过import "file Path"
导入一个文件,而不把任何变量纳入你的当前模块:
// @filename: a.ts(与 hello.ts同级)
import "./hello";
在这种情况下, import
没有任何作用,但 hello.ts
中的所有代码都将被解析,这可能引发影响其他对象的副作用
类型可以使用与JavaScript
值相同的语法进行导出和导入:
// @filename: hello.ts
export type Cat = {};
export interface Dog {}
// @filename: a.ts(与 hello.ts同级)
import { Cat, Dog } from "./hello";
let a: Cat, b: Dog;
TypeScript
用两个概念扩展了 import
语法,用于声明一个类型的导入:
import type
这是一个导入语句,导入的变量只能用作类型:
// @filename: hello.ts
export const createCatName = () => "fluffy";
内联类型导入
TypeScript 4.5
还允许以type
为前缀的单个导入,以表明导入的引用是一个类型:
// @filename: hello.ts
export type Cat = {};
export interface Dog {}
export const createCatName = () => "fluffy";
// @filename: a.ts(与 hello.ts同级)
// 表明Cat和Dog为类型
import { createCatName, type Cat, type Dog } from "./hello";
type Animals = Cat | Dog;
const name = createCatName();
若使用CommonJS语法报错,则需要先在项目根目录运行:
npm i --save-dev @types/node
安装声明文件
通过在一个全局调用的 module
上设置 exports
属性来导出:
// @filename: hello.ts
function absolute(num: number) {
return num;
}
const a = 3;
let b = 4;
var c = 5;
module.exports = {
a,
b,
newC: c, // 将c以newC的名称导出
d: 12, // 直接导出一个值
fn: absolute, // 将absolute以fn的名称导出
};
通过require
语句导入:
// @filename: a.ts(与 hello.ts同级)
const m = require("./hello");
console.log(m.a, m.b, m.newC, m.fn(1));
使用JavaScript
中的解构功能来简化一下:
// @filename: a.ts(与 hello.ts同级)
const { d, fn } = require("./hello");
console.log(d, fn(1));
模块解析是指从import
或require
语句中获取一个字符串,并确定该字符串所指的文件的过程
TypeScript
包括两种解析策略:
Node
当编译器选项(tsconfig.json
配置文件)中 module
不是commonjs
时,经典策略是默认的,是为了向后兼容。
Node
策略复制了Node.js
在CommonJS
模式下的工作方式,对.ts
和.d.ts
有额外的检查
在TypeScript
中,有许多TSConfig
标志影响模块策略:
关于这些策略如何工作的全部细节,你可以参考《模块解析》
tsconfig.json
配置文件中有两个选项影响JavaScript
的输出:
target
,它决定了TS
代码编译成JS
的版本module
,它决定了哪些代码用于模块之间的相互作用所有模块之间的通信都是通过模块加载器进行的,编译器选项 module
决定了使用哪一个
在运行时,模块加载器负责在执行一个模块之前定位和执行该模块的所有依赖项
可以在TSConfig 模块参考 中看到所有可用的选项以及它们编译出的JavaScript
代码是什么样子
TypeScript
有自己的模块格式,称为 命名空间(namespaces)
,这比ES
模块标准要早
这种语法对于创建复杂的定义文件有很多有用的功能,并且在DefinitelyTyped
中仍然被积极使用。虽然没有被废弃,但命名空间中的大部分功能都存在于ES Modules
中,官方建议使用它来与JavaScript
的方向保持一致
更多关于命名空间的信息可见: namespaces参考页
至此,TypeScript
模块化的内容就全部结束了,关注博主下篇更精彩!
博主的TypeScript从入门到精通专栏正在慢慢的补充之中,赶快关注订阅,与博主一起进步吧!期待你的三连支持。
参考资料:TypeScript官网
如果本篇文章对你有所帮助,还请客官一件四连!❤️