2023年6月20日发(作者:)
elementui的css⽂件没有引⼊_typescript声明⽂件加载机制以及在不同场景。。。. ⽂件是 typescript 的声明⽂件,主要⽤来给编辑器做代码提⽰⽤,具体的书写位置和⽅式根据你的具体需求⽽定。(嫌弃太长可以直接跳到使⽤⽅式的 1.1 和 2.3)很多初学者(⽐如我)刚开始接触 ts 时,⼀直分不清 .ts 和 . 的区别,不知道 . 存在的意义是什么。刚开始跟着各种教程搭建好了ts 开发环境,写好了 hello world 时,发现就算没有写 . ⽂件,编辑器(这⾥以及之后的编辑器均指宇宙第⼀编辑器 vscode )也可以获得代码提⽰,甚⾄就算写的不是 ts ⽽是 js,只要 import 的依赖关系明确,对于⼀些简单的函数依然能获得最基本的⼊参、返回值的形参提⽰。从⽽就想知道 . ⽂件存在的意义是什么。其实这个问题稍微思考⼀下就能知道。假设我们⽤ ts 开发了⼀个 npm 库,经过编译打包之后发布到了 npm 上,其他⽤户下载了我们这个库,下载到他本地的⼀般是⼀个 dist/ , ⾥的 main 指向这个 dist/ ⽂件。这时候不管这个⽤户开发使⽤的是 ts 还是 js,当他 import 我们这个库的时候都⽆法获得代码提⽰。. ⽂件主要是 for 第三⽅库,让第三⽅库的使⽤者可以获得良好的代码和接⼝提⽰。本⽂主要介绍 . ⽂件的加载机制以及在纯. ⽂件主要是 for 第三⽅库,让第三⽅库的使⽤者可以获得良好的代码和接⼝提⽰纯js开发环境中如何使⽤ . 声明⽂件,获得代码提⽰和接⼝声明。js加载机制⼀些定义:三斜线指令定义: ///
import c from "./c";
declare const index = 1;
export default index;// node_modules/@types/my/are const a = 1;// node_modules/@types/my/are const b = 1;// node_modules/@types/my/are const c = 1;export default c;上⾯的代码的效果为:全局:a、b⾮全局: index、cindex ⽂件中,由于含有 import export,所以为模块类声明⽂件,⾥⾯使⽤ declare 声明的 index 为⾮全局,在被使⽤时只有 importindex from 'my';时才能拿到 index。⽽引⼊的 a、b ⽂件,这两个⽂件虽然是被 index 这个模块类声明⽂件引⼊的,但是这两个⽂件⾃⼰本⾝是全局类声明⽂件(既没有 import 也没有 export),所以这两个⽂件⾥⾯ declare 的变量都可以在全局访问到。⽽引⼊的 c ⽂件⾥⾯含有 export,所以为模块⽂件,⾥⾯的 c ⽆法在全局被访问。FAQ | Tips | 注意事项:1. 既然 a、b ⽂件为全局类声明⽂件,那么为什么还要在 index 中引⼊?因为⼀般情况下 的 exclude 会加⼊ node_modules,所以理论上 node_modules ⾥⾯的所有⽂件都不会被 ts 编译。⽽node_modules/@types ⽐较特别,⾥⾯的每个包会被作为⼀个模块,这个模块只会有⼀个⼊⼝⽂件(⽐如默认的 )。这个⼊⼝⽂件中没有引⼊的,都不会被 ts 处理。所以上⾯的代码在 index ⽂件中去掉【import "./b";】 之后,b ⽂件中的【declare const b =1;】不会被 ts 看到(a 同理)。2. import 和 ///
这种情况只能导出⼀个 namespace:export const d = 1;
export as namespace whateverthisis; // 全局 namespace 名,whateverthisis.d 就可以访问到(export as namespace 只能在模块⽂件⾥⾯使⽤)4. vscode 的 ts 代码提⽰的缓存机制vscode 的 ts 代码提⽰会缓存 node_modules/@types 下的每个 package 的⼊⼝⽂件地址( 的 main 字段)。如果⼿动去改变了某个包的 main 字段,改成了另⼀个⽂件,那么在重启 ts server(vs code⾃带的⼀个东西),修改是不会⽣效的,⼊⼝⽂件依旧是以前的⼊⼝⽂件(但是去修改⼊⼝⽂件⾥的内容是可以⽣效的)5. declare module A 和 declare module 'a' 的区别前者已经被废弃,使⽤ declare namespace A代替;后者⽤于扩展⼀个已有的模块 a。全局⽂件下的 declare module 'xx' 会在全局环境⽣成⼀个名为 xx 的模块,并且可以在⾥⾯定义这个 xx 模块应该有的导出,⼀般⽤来添加或补充 node_modules 中的模块的声明⽂件。同名的 declare module ⾥⾯的导出会合并。使⽤⽅式常⽤的是下⾯的 1.11.1 、2.32.31. 添加全局的代码提⽰(直接输⼊变量即可获得代码提⽰)1.1 添加⾃定义全局变量场景:全局注⼊变量,⽐如⼩程序的 Page正确操作:正确操作// (简化版)interface Opt
}
declare function Page
return ((result, value) => result + value, 0);
}正确操作:正确操作// rface Array
getSum(): T extends number ? number : void;
}场景2:给 jQuery 加⼀个静态⽅法 $.getHelloWorld通过简单分析(opt+click)可以知道,暴露在全局的 jQuery 和 $ 本⾝是两个全局的 const 常量,类型是 JQueryStatic,所以只需要给这个 JQueryStatic 接⼝增加 getHelloWorld ⽅法就可以了。正确操作:正确操作// rface JQueryStatic {
getHelloWorld(): string;
}场景3:给 lodash 加⼀个静态⽅法 _.getHelloWorld通过简单分析(opt+click)可以知道,暴露在全局的 _ 本⾝是⼀个 const 变量,类型为 _.LoDashStatic,但是这个 _.LoDashStatic 并没有被暴露到全局,所以需要使⽤ declare module 的语法来 override lodash 这个模块正确操作:正确操作// (和 分开,否则会使 中的 declare 失去全局性)import _ from 'lodash'; // 注意这个 import 必须写在 declare module 外部
declare module 'lodash' { interface LoDashStatic { getHelloWorld(): string;
}
}2.2 扩展⾮全局模块,但⾃带声明⽂件的模块(esm、commonjs)场景:node 的 fs 增加⼀个 getHelloWorld ⽅法先通过npm i @types/node -D安装 node 的声明⽂件正确操作:正确操作// are module 'fs' {
export function getHelloWorld(): string;
}2.3 扩展⾮全局模块,并且不⾃带声明⽂件的模块场景1:你从 npm 上⾯下载了⼀个 ex-module 模块,但是这个作者很懒,没有提供声明⽂件,@types 社区也没有⼈提供,你想⾃⼰给 ex-module 写声明⽂件,便于后续开发假设 ex-module 长这样:// node_modules/ex-module/rt _ from 'lodash';
export function add(a, b) { return a + b; }
export function minus(a, b) { return a - b; }
export default function getLodash() { return _; }正确操作:正确操作// are module 'ex-module' {
import { LoDashStatic } from 'lodash'; // 注意这个 import 必须写在 declare module 内部
export function add(): number;
export function minus(): number;
export default function getLodash(): LoDashStatic;
}// rt getLodash,{ add, minus } from 'ex-module';add(1, 130);坑点:由于 js + ts 模块化过于混乱,各⾃的实现也有冲突,建议全部严格按照 ES6 的⽅式来写⽐如上⾯的 中,如果删掉 export default 宇航,在 中 import ex from 'ex-module',输⼊ ex 时候, vscode 会提⽰ 是⼀个函数,但实际上 ex 是 undefined场景2:你⽤ js 给⾃⼰写了⼀个 util 库,⾥⾯有各种各样的⼯具函数,想给他们加上声明⽂件// util/rt function add(a, b) {
return a + b;
}
export function minus(a, b) {
return a - b;
}正确操作:正确操作// util/rt function add(a: number, b: number): number;
export function minus(a: number, b: number): number;总结: ts 由于各种复杂的历史遗留问题,模块⽅⾯⽐较混乱,坑也很多,还是建议统⼀⽤ ES6 模块
2023年6月20日发(作者:)
elementui的css⽂件没有引⼊_typescript声明⽂件加载机制以及在不同场景。。。. ⽂件是 typescript 的声明⽂件,主要⽤来给编辑器做代码提⽰⽤,具体的书写位置和⽅式根据你的具体需求⽽定。(嫌弃太长可以直接跳到使⽤⽅式的 1.1 和 2.3)很多初学者(⽐如我)刚开始接触 ts 时,⼀直分不清 .ts 和 . 的区别,不知道 . 存在的意义是什么。刚开始跟着各种教程搭建好了ts 开发环境,写好了 hello world 时,发现就算没有写 . ⽂件,编辑器(这⾥以及之后的编辑器均指宇宙第⼀编辑器 vscode )也可以获得代码提⽰,甚⾄就算写的不是 ts ⽽是 js,只要 import 的依赖关系明确,对于⼀些简单的函数依然能获得最基本的⼊参、返回值的形参提⽰。从⽽就想知道 . ⽂件存在的意义是什么。其实这个问题稍微思考⼀下就能知道。假设我们⽤ ts 开发了⼀个 npm 库,经过编译打包之后发布到了 npm 上,其他⽤户下载了我们这个库,下载到他本地的⼀般是⼀个 dist/ , ⾥的 main 指向这个 dist/ ⽂件。这时候不管这个⽤户开发使⽤的是 ts 还是 js,当他 import 我们这个库的时候都⽆法获得代码提⽰。. ⽂件主要是 for 第三⽅库,让第三⽅库的使⽤者可以获得良好的代码和接⼝提⽰。本⽂主要介绍 . ⽂件的加载机制以及在纯. ⽂件主要是 for 第三⽅库,让第三⽅库的使⽤者可以获得良好的代码和接⼝提⽰纯js开发环境中如何使⽤ . 声明⽂件,获得代码提⽰和接⼝声明。js加载机制⼀些定义:三斜线指令定义: ///
import c from "./c";
declare const index = 1;
export default index;// node_modules/@types/my/are const a = 1;// node_modules/@types/my/are const b = 1;// node_modules/@types/my/are const c = 1;export default c;上⾯的代码的效果为:全局:a、b⾮全局: index、cindex ⽂件中,由于含有 import export,所以为模块类声明⽂件,⾥⾯使⽤ declare 声明的 index 为⾮全局,在被使⽤时只有 importindex from 'my';时才能拿到 index。⽽引⼊的 a、b ⽂件,这两个⽂件虽然是被 index 这个模块类声明⽂件引⼊的,但是这两个⽂件⾃⼰本⾝是全局类声明⽂件(既没有 import 也没有 export),所以这两个⽂件⾥⾯ declare 的变量都可以在全局访问到。⽽引⼊的 c ⽂件⾥⾯含有 export,所以为模块⽂件,⾥⾯的 c ⽆法在全局被访问。FAQ | Tips | 注意事项:1. 既然 a、b ⽂件为全局类声明⽂件,那么为什么还要在 index 中引⼊?因为⼀般情况下 的 exclude 会加⼊ node_modules,所以理论上 node_modules ⾥⾯的所有⽂件都不会被 ts 编译。⽽node_modules/@types ⽐较特别,⾥⾯的每个包会被作为⼀个模块,这个模块只会有⼀个⼊⼝⽂件(⽐如默认的 )。这个⼊⼝⽂件中没有引⼊的,都不会被 ts 处理。所以上⾯的代码在 index ⽂件中去掉【import "./b";】 之后,b ⽂件中的【declare const b =1;】不会被 ts 看到(a 同理)。2. import 和 ///
这种情况只能导出⼀个 namespace:export const d = 1;
export as namespace whateverthisis; // 全局 namespace 名,whateverthisis.d 就可以访问到(export as namespace 只能在模块⽂件⾥⾯使⽤)4. vscode 的 ts 代码提⽰的缓存机制vscode 的 ts 代码提⽰会缓存 node_modules/@types 下的每个 package 的⼊⼝⽂件地址( 的 main 字段)。如果⼿动去改变了某个包的 main 字段,改成了另⼀个⽂件,那么在重启 ts server(vs code⾃带的⼀个东西),修改是不会⽣效的,⼊⼝⽂件依旧是以前的⼊⼝⽂件(但是去修改⼊⼝⽂件⾥的内容是可以⽣效的)5. declare module A 和 declare module 'a' 的区别前者已经被废弃,使⽤ declare namespace A代替;后者⽤于扩展⼀个已有的模块 a。全局⽂件下的 declare module 'xx' 会在全局环境⽣成⼀个名为 xx 的模块,并且可以在⾥⾯定义这个 xx 模块应该有的导出,⼀般⽤来添加或补充 node_modules 中的模块的声明⽂件。同名的 declare module ⾥⾯的导出会合并。使⽤⽅式常⽤的是下⾯的 1.11.1 、2.32.31. 添加全局的代码提⽰(直接输⼊变量即可获得代码提⽰)1.1 添加⾃定义全局变量场景:全局注⼊变量,⽐如⼩程序的 Page正确操作:正确操作// (简化版)interface Opt
}
declare function Page
return ((result, value) => result + value, 0);
}正确操作:正确操作// rface Array
getSum(): T extends number ? number : void;
}场景2:给 jQuery 加⼀个静态⽅法 $.getHelloWorld通过简单分析(opt+click)可以知道,暴露在全局的 jQuery 和 $ 本⾝是两个全局的 const 常量,类型是 JQueryStatic,所以只需要给这个 JQueryStatic 接⼝增加 getHelloWorld ⽅法就可以了。正确操作:正确操作// rface JQueryStatic {
getHelloWorld(): string;
}场景3:给 lodash 加⼀个静态⽅法 _.getHelloWorld通过简单分析(opt+click)可以知道,暴露在全局的 _ 本⾝是⼀个 const 变量,类型为 _.LoDashStatic,但是这个 _.LoDashStatic 并没有被暴露到全局,所以需要使⽤ declare module 的语法来 override lodash 这个模块正确操作:正确操作// (和 分开,否则会使 中的 declare 失去全局性)import _ from 'lodash'; // 注意这个 import 必须写在 declare module 外部
declare module 'lodash' { interface LoDashStatic { getHelloWorld(): string;
}
}2.2 扩展⾮全局模块,但⾃带声明⽂件的模块(esm、commonjs)场景:node 的 fs 增加⼀个 getHelloWorld ⽅法先通过npm i @types/node -D安装 node 的声明⽂件正确操作:正确操作// are module 'fs' {
export function getHelloWorld(): string;
}2.3 扩展⾮全局模块,并且不⾃带声明⽂件的模块场景1:你从 npm 上⾯下载了⼀个 ex-module 模块,但是这个作者很懒,没有提供声明⽂件,@types 社区也没有⼈提供,你想⾃⼰给 ex-module 写声明⽂件,便于后续开发假设 ex-module 长这样:// node_modules/ex-module/rt _ from 'lodash';
export function add(a, b) { return a + b; }
export function minus(a, b) { return a - b; }
export default function getLodash() { return _; }正确操作:正确操作// are module 'ex-module' {
import { LoDashStatic } from 'lodash'; // 注意这个 import 必须写在 declare module 内部
export function add(): number;
export function minus(): number;
export default function getLodash(): LoDashStatic;
}// rt getLodash,{ add, minus } from 'ex-module';add(1, 130);坑点:由于 js + ts 模块化过于混乱,各⾃的实现也有冲突,建议全部严格按照 ES6 的⽅式来写⽐如上⾯的 中,如果删掉 export default 宇航,在 中 import ex from 'ex-module',输⼊ ex 时候, vscode 会提⽰ 是⼀个函数,但实际上 ex 是 undefined场景2:你⽤ js 给⾃⼰写了⼀个 util 库,⾥⾯有各种各样的⼯具函数,想给他们加上声明⽂件// util/rt function add(a, b) {
return a + b;
}
export function minus(a, b) {
return a - b;
}正确操作:正确操作// util/rt function add(a: number, b: number): number;
export function minus(a: number, b: number): number;总结: ts 由于各种复杂的历史遗留问题,模块⽅⾯⽐较混乱,坑也很多,还是建议统⼀⽤ ES6 模块
发布评论