首页 > 其他分享 >TS 导入导出那些事

TS 导入导出那些事

时间:2023-04-07 22:37:13浏览次数:39  
标签:123 导出 TS 导入 export 模块 import mod

前言

最近用 TypeScript 写 npm 包,各种模块、命名空间、全局定义等等扰得我睡不着觉。

我便苦心研究,总结了几个比较冷门的,国内貌似基本上找不到资料的导入导出用法,顺便在其中又插入一些不那么冷门的用法,于是本篇文章来了。

因为一开始也没想做成大全,可能之后还会继续更新吧。

目录

导入模块

导入模块中的东西相信大家都不陌生。唯一需要注意的便是默认导出与“星号”导出的区别。

import * as Mod from './mod';
// 类似于
const Mod = require('./mod');
import ModDef from './mod';
// 类似于
const { default: ModDef } = require('./mod');
import ModDef, { a, b } from './mod';

// 类似于
const {
	default: ModDef,
	a, b
} = require('./mod');

在模块中导出

在模块中导出东西相信大家也不陌生,不过这里还是详细讲解一下。

在模块中导出东西有很多种方法。导出总共可分为 4 类:

命名导出

命名导出有两种方法,一种是声明着导出

export namespace A { }
export function b() { }
export class C { }
export const d = 123;
export let { e } = { e: 'hh' };

一种是声明后导出

namespace A { }
function b() { }
class C { }
const d = 123;
let { e } = { e: 'hh' };

export { A, b, C, d, e };

声明后导出比声明着导出更灵活,能合并,也能重命名

namespace A { }
export { A };

function b() { }
export { b as c };

class C { }
export { C as B };

const d = 123;
let { e } = { e: 'hh' };
export { d, e };

命名导出编译成 Common JS 后类似这样

exports.xxx = xxx;

需要注意的是其他人无法修改任何你导出的东西。即使是使用 let 声明也一样

/* mod.ts */
export let a = 123;

/* others.ts */
import { a } from './mod';
a = 321; // 报错:ts(2632)

不过对于上面的代码,你可以随便修改所导出的 a 。因为其他人每次读取 a 时都会重新从你的导出对象上访问一次 a 属性,不用担心其他人无法接收到你的修改。具体可以查看编译后的 JS 文件

/* others.ts */
import { a } from './mod';
const b = a + 123;
console.log(a);

/* others.js */
var mod_1 = require("./mod");
var b = mod_1.a + 123;
console.log(mod_1.a);

默认导出

默认导出可以理解为一种特殊的命名导出。

默认导出的名字是 default 。但是你不能搞个名字叫 default 的变量然后导出,你必须得用 export default 或者在导出时重命名

export let default = 123; // 报错:ts(1389)

export default 123; // 正确

export let a = 123;
export { a as default }; // 正确

星号导出

星号导出可以导出其他模块里的东西。一般有两种用法。

第一种是全导出到自己里头,就像

export * from './xxx'

具体效果是 xxx 中导出的东西,也可以通过你访问到。

/* xxx.ts */
export let a = { hh: 'hh' };

/* mod.ts */
export * from './xxx.ts';

/* others.ts */
import { a } from './xxx';
import { a } from './mod';
console.log(a === a); // true

第二种是挂到自己模块下面,就像

export * as xxx from './xxx';
// 等价于
import * as xxx from './xxx';
export { xxx };

星号导出搭配默认导出,可以达到默认导出即为全部导出的效果

/* mod.ts */
import * as Self from './mod';
export default Self;

/* others.ts */
import * as Mod from './mod';
import ModDef from './mod';
console.log(Mod === ModDef); // true

导出分配

导出分配就是把 Common JS 的导出搬到了 TS 中。写法也差不多

export = 'hh';
// 相当于
module.export = 'hh';

导出分配也可以指定默认导出,只需要有 default 属性就可以

/* mod.ts */
export = { default: 123 };

/* others.ts */
import mod from './mod';
console.log(mod); // 123

需要注意的是采用了导出分配后便不能再使用其他导出方法。

导入命名空间

虽然现在命名空间相较于模块并不是特别常用,但它还是有比较完整的导入导出功能的。

导入命名空间中的东西很简单,像这样

import xxx = Space.xxx;

不论你是在模块中导入全局命名空间,还是在命名空间中导入其他命名空间,都是适用的。

import Err = globalThis.Error;
throw Err('hh');

namespace A {
	import Process = NodeJS.Process;
	let proce: Process;
}

较为可惜的是命名空间貌似没有星号导入,也不支持解构导入。

在命名空间中导出

在一般 TS 中,命名空间只有两种方法导出。

第一种方法是声明着导出,类似于模块

namespace A {
	export const a = 123;
}

第二种方法是导入着导出,可以用来导出其他命名空间的东西

namespace A {
	export import Err = globalThis.Error;
}

而对于不一般的 TS ——也就是类型声明中,命名空间还可以采用像模块一样的导出对象

declare namespace A {
	const a = 123;
	const b = 'hh';
	export { a, b };
}

使用全局定义

全局定义一般有三种:

  1. 内置在 TS 中的全局定义。比如 setTimeoutError 等。
    对于这种全局定义,直接拿来用就可以了。

  2. 位于环境模块中的全局定义。比如 NodeJS.Process 等。

    包括位于 node_modules/@types 文件夹中的自动引入的环境模块,都可以通过三斜杠注释来引入。

    你可以通过 path 直接指定文件路径

    /// <reference path="./types.d.ts" />
    
  3. 位于模块中的全局定义。

    这种全局定义只需要引入一下模块,表示你已经运行此模块,即可

    import '@babel/core';
    

    或者你也可以通过三斜杠注释,通过 types 指定模块

    /// <reference types="@babel/core" />
    

    需要注意的是,不论你采用 import 还是三斜杠注释,甚至只是在类型中使用了一个 typeof import('xxx') ,只要你在一个 TS 文件中引入了这个模块所定义的全局类型,那这个类型就会永远存在下去,污染你的 globalThis
    唯一在不污染全局域的情况下运行模块的方法是使用 import() 函数动态引入,但这样子你也拿不到你需要的类型。

进行全局定义

进行全局定义一般有三种方法。

第一种是直接写环境模块。不带任何 importexport 一般就会让编译器把这当成一个环境模块。所以,如果你需要防止一个 TS 文件变成环境模块导致类型泄露的话,你可以加一个安全无公害的 export { };

第二种是在模块中定义,只需要把类型定义写到 declare global 里头就行

declare global {
	const a = 123;
	let b: {};
}

a; // 123
b; // {}

第三种是通过合并 globalThis 命名空间来定义,好处是可以使用命名空间的“导入着导出”方法,将模块或者其他命名空间的局部变量变成全局变量

import _Mod from './mod';

declare global {
	namespace globalThis {
		const a = 123;
		export import Mod = _Mod;
	}
}

a; // 123
Mod; // typeof import('./mod')

标签:123,导出,TS,导入,export,模块,import,mod
From: https://www.cnblogs.com/QiFande/p/ts-about-export.html

相关文章

  • 关于s3-bucket使用client.list_objects_v2列出所有的对象与指定目录下的所有对象
    使用AWSSDKforPython(Boto3)的S3的client下的list_objects_v2,可以列出一个s3bucket桶的所有对象,可以返回如下几个重要的字段的Key,LastModified,ETag,Size,StorageClass 实现的核心代码如下:其中在编辑中,有几个说明如下:1、Console页面上可以创建一个空的文件夹,......
  • 【题解】P4898 [IOI2018] seats 排座位
    思路线段树。题意可以转化成每次判定有多少个前缀满足所有结点构成矩形。首先排除确定矩阵坐标再数答案的做法,因为太难。所以考虑如何对前缀进行判定。一个简单的想法是维护前\(i\)个点中\(x,y\)坐标的最值,但这样只能暴力看矩阵中的所有元素,跑得很慢。不妨思考一下合法......
  • 【题解】CF472G Design Tutorial: Increase the Constraints
    《正解分块+FFT跑1min,__builtin_popcount暴力跑10s》《没人写正解,CF也不卡》思路正解:分块+FFT乱搞:__builtin_popcount首先我们知道哈明距离可以用一种\(O(|字符集||S|)\)的算法求。具体考虑枚举字符集中的每一个字符,将两个串中是该字符的位置看作\(1\),不是该字......
  • odoo 开发入门教程系列-约束(Constraints)
    约束(Constraints)上一章介绍了向模型中添加一些业务逻辑的能力。我们现在可以将按钮链接到业务代码,但如何防止用户输入错误的数据?例如,在我们的房地产模块中,没有什么可以阻止用户设置负预期价格。odoo提供了两种设置自动验证恒定式的方法:Python约束andSQL约束。SQL参考:与此......
  • flask框架04 导出项目 local flask生命执行流程 wtforms
    今日内容详细目录今日内容详细1请求上下文分析(源码:request原理)1.1导出项目的依赖1.2函数和方法1.3threading.local对象1.4偏函数1.5flask整个生命执行流程(1.1.4版本为例)2wtforms(了解)1请求上下文分析(源码:request原理)1.1导出项目的依赖#之前pipfreeze>requ......
  • mysqldump 命令导出数据,解决中文乱码问题
      https://www.cnblogs.com/LoveBB/p/16941639.html mysqldump-uroot-ppassword--add-drop-table--default-character-set=utf8--hex-blobdbname--result-file=F:\backup.sql......
  • vue导入处理Excel表格详解
    https://blog.csdn.net/m0_46309087/article/details/125022676 目录1.前言2.vue导入Excel表格2.1使用ElementUI中的upload组件2.2使用input文件上传3.总体代码与效果4.总结1.前言  最近遇到前端导入并处理excel表格的情况,趁此机会刚好研究一下vue导入并处理excel数据;......
  • IDEA导入普通web项目
    公司项目是普通web项目,导入使用IDEA启动需要一定的步骤,在此做下记录在IDEA中依次点击File->New->ProjectfromExistingSources选中项目目录之后直接下一步下一步下一步。然后点击File->ProjectStructure在Project面板修改SDK版本在Modules面板中的Sources面板把res......
  • mybaits-plus优雅的实现数据权限
    前言项目使用mybaits-plus,所以在mybaits-plus的基础上增加数据权限的过滤mybaits-plus自带数据权限支持,但由于系统数据权限相对复杂,通过查看文档发现好像并不适用,且原项目版本低,所以最终还是通过自己的方式实现数据范围我们系统相对复杂,比如可以按机构/用户等多种维度过滤,并且可以......
  • error TS9005: Declaration emit for this file requires using private name 'xxx'.
    errorTS9005:Declarationemitforthisfilerequiresusingprivatename'distance'.Anexplicittypeannotationmayunblockdeclarationemit.代码如下:/***计算两个坐标之间的距离*@parampnt1*@parampnt2*@returns{number}*@constructor*/expor......