作用
ts的编写的模块最终对外暴露时是编译为js的(各种第三方工具包、组件库..), 因此外部使用时会失去类型提示, 声明文件可以为外部提供类型提示
示例
在编译打包时的配置文件tsconfig.json中加入 declaration: true
tsconfig.build.json
{
"compilerOptions": {
"outDir": "dist",
"module": "esnext",
"target": "es5",
"declaration": true, // here
"jsx": "react",
"moduleResolution":"Node",
"allowSyntheticDefaultImports": true,
"skipLibCheck": true
},
"include": [
"src"
],
"exclude": [
"src/**/*.test.tsx",
"src/**/*.stories.tsx",
"src/setupTests.ts",
"stories/**/*.svg",
"stories/**/*.mdx"
]
}
exam package.json 配置
"scripts": {
"build": "tsc -p tsconfig.build.json"
},
这样会对所有ts/tsx文件进行d.ts生成,当然,我们也可以手动编写声明文件。
在需要类型声明的文件同目录下建立同名的d.ts并编写即可,如 button.tsx 对应 button.d.ts
编写姿势
各种编写方式
// const dom:HTMLElement = jQuery('#id') √
// const dom:string = jQuery('#id') ×
let jQuery: (selector: string) => HTMLElement; // 定义已有的变量(如npm引入的jquery,但没有引入typing文件的话,就在这里手动定义,但是现在的包一般都有typing文件了)
// const fn:sayHello = (a:string) => return a + 'hello' √
type sayHello = (a: string) => string;
// window.ga() √
interface Window {
ga: () => void;
}
// const a = new Animal('jenson')√
// a.name = 'new name' √
// a.sayHi = ()=> 'hi' √
// const a = new Animal(10) ×
// a.name = 10 ×
// a.sayHi = () => 10 ×
declare class Animal {
name: string;
constructor(name: string);
sayHi(): string;
}
// const o:OO = (name: number) => return name √
interface OO {
name: number;
}
// const o:n1.OO = (name: string) => return name √
namespace n1 {
interface OO {
name: string;
}
}
ps: 发现declare关键字写不写都能全局生效,可能编译器自动自动识别了
编写类库声明
dist/env/index.js
var regExec = function (patt) {
return patt.exec(userAgent);
};
/**
* 获取APP版本号
* @return {String} 4.3.0
*/
var getAppVersion = function () {
var res = regExec(appVersionPatt);
return res ? res[2] : "";
};
// 是否安卓APP
var isAndroid = !!regExec(androidPatt);
// 是否iOS APP
var isIos = !!regExec(iosPatt);
// 是否在APP内
var isApp = !!regExec(isAppPatt);
export default {
getAppVersion: getAppVersion,
isAndroid: isAndroid,
isIos: isIos,
isApp: isApp,
};
dist/env/index.d.ts
declare const env: {
getAppVersion: () => any;
isAndroid: boolean;
isIos: boolean;
isApp: boolean;
};
或
declare namespace env {
function getAppVersion(): any;
const isAndroid: boolean;
const isIos: boolean;
const isApp: boolean;
}
export default env;
namespace和module作用是一致的,但ts推荐使用namespace,避免和es的module混淆
__test__.ts
import env from "./dist/env";
let a0:boolean = env.isApp // ok
let a: string = env.isApp; // error
拓展window全局方法
有时我们引入了一些第三方包如微信sdk, 其暴露的对象wx是挂载到window上了, 直接使用会被提示找不到该对象
在根目录添加global.d.ts (随意取名)
declare interface Window {
wx:any;
}
tsconfig.json
"compilerOptions": {
"typeRoots": ["global.d.ts"],
"include": ["src", "global.d.ts"] // 这里一定要包含声明文件的目录
}