使用Typescript给JavaScript做静态类型检查
栏目: JavaScript · 发布时间: 6年前
内容简介:笔者所说的这个项目,是一个运行了接近五年的老项目,代码横跨es3到es6。而且代码风格由于项目的人员流动也各异。由于项目人数越来越多,以前留下的技术债造成的危害也越来越大。而重构,在这样一个臃肿且混乱的项目中显得举步维艰。由于JS的动态性,有的时候你甚至不知道这个方法是某个类下的实例方法还是JavaScript原生或是JQuery所提供的方法。 这个时候,TypeScript由于其提供的强类型能很好的规范代码,方便开发人员进行日常开发和重构,开始进入了我们的视野。 但是马上我们面对上了另一个难题,那就是,
笔者所说的这个项目,是一个运行了接近五年的老项目,代码横跨es3到es6。而且代码风格由于项目的人员流动也各异。由于项目人数越来越多,以前留下的技术债造成的危害也越来越大。而重构,在这样一个臃肿且混乱的项目中显得举步维艰。由于JS的动态性,有的时候你甚至不知道这个方法是某个类下的实例方法还是JavaScript原生或是JQuery所提供的方法。 这个时候,TypeScript由于其提供的强类型能很好的规范代码,方便开发人员进行日常开发和重构,开始进入了我们的视野。 但是马上我们面对上了另一个难题,那就是,我们只想享受TypeScript强类型带来的类型推导的优势,并不想花大功夫去把整个代码库全部重构成TypeScript。 不过好在,TypeScript从2.3版本后就开始支持使用JsDoc的语法,以comment的形式给JavaScript文件提供强类型的支持。 Type Checking JavaScript Files · TypeScript
如何开始使用Type Checking
首先你需要在你需要检查的JavaScript的文件头部显式的加上如下comment
// @ts-check 复制代码
对变量进行类型检查
如果你需要声名一个变量的类型,你可以这样
/** @type {number} */ let x; x = 0; // OK x = false; // Error: boolean is not assignable to number 复制代码
当你尝试给x赋一个bool值时,编辑器会提示你类型冲突。
对函数进行类型检查
当然某些时候我们最需要的其实是对于函数签名和返回值的强类型声名,以便我们在其他地方使用的时候不会传入错误的参数或者使用类型错误的函数返回值。TypeScript提供了三种语法来声名函数的类型.
// jsdoc standard syntax // 声明一个函数 /** * @param {string} foo * @param {string} bar * @returns {string} */ function test(foo, bar) { return `${foo} and ${bar}` } // closure syntax // 声明一个函数表达式 /** * @type {function(string, string): string} */ let test; // test 必须符合定义的函数签名 test = (foo, bar, foobar) => '123' // 报错 函数不符合定义的签名 test = (foo, bar) => 1 // 报错 函数返回值不符合 // typescript like syntax // 声明一个函数表达式 /** * @type {(foo:string, bar:string) => string} */ let test; // test 必须符合定义的函数签名 复制代码
在日常使用中,如果你想声明一个函数,对于函数做类型检查,你需要使用 @params
@returns
这种declaration 语法。
如果你想确定一个函数表达式的签名,你需要使用 @type
的语法。
对于 @type
语法, 从表现力上,我个人更偏好 typscript like syntax
因为表达力最强。但是可惜的是这种语法在webstorm上会被认为是非法语法。
自定义类型
自定义类型有点类似于定义TypeScript中的Interface,TypeScript同样支持两种语法来自定义类型。
/** * @typedef {Object} Human * @prop {string} name * @property {number} age * @prop {(string) => void} talk */ /** @type {Human} */ let Human; /** * @typedef {{name: string, age:number, talk: (string) => void}} Person */ /** @type {Person}*/ let person; 复制代码
需要注意的是,第二种语法在webstorm中也不被认为只一个合法的语法。
声明一个class
对于类的property的类型,可以很轻松的进行检查
// 有初始化值,可以依赖类型推导 class C { constructor() { this.constructorOnly = 0 this.constructorUnknown = undefined } method() { this.constructorOnly = false // error, constructorOnly is a number this.constructorUnknown = "plunkbat" // ok, constructorUnknown is string | undefined this.methodOnly = 'ok' // ok, but y could also be undefined } method2() { this.methodOnly = true // also, ok, y's type is string | boolean | undefined } } // 无初始化值,显式声明. class C { constructor() { /** @type {number | undefined} */ this.prop = undefined; /** @type {number | undefined} */ this.count; } } let c = new C(); c.prop = 0; // OK c.count = "string"; // Error: string is not assignable to number|undefined 复制代码
对于类的实例方法,你需要对于函数做出声明.
class Foo { /** * @param {string} binggo * @returns {string} */ bar(bingo) { return bingo; } } let test2 = new Foo() test2.bar(1); // Error Emit. 复制代码
其他的一些特性
可选参数
/** * @param {string} [somebody] - Somebody's name. */ function sayHello(somebody) { if (!somebody) { somebody = 'John Doe'; } console.log('Hello ' + somebody); } sayHello(); 复制代码
类型union
/** * @type {(string | boolean)} */ var sb; 复制代码
三方类型
三方类型在这里既可以是 npm提供的 @types
包,也可以是自己在项目中通过TypeScript定义的类型。 只要在typeRoots这个编译器选项中指明即可。
如何和项目做集成
IDE和编辑器集成
项目以使用vscode和webstorm为主,但是理论上,只要能支持 TypeScript Language Server Protocal 的编辑器都不会出现集成上的问题。
vscode
对于vscode,不需要做过多的配置,直接在文件头部加入 // @ts-check
的comment就可以开启TypeScript checking.
WebStorm
对于WebStorm,你需要提供对应的 tsconfig.json
文件来显式的打开这个特性。
{ "compilerOptions": { "allowJs": "true", // 开启js checking "noEmit": "true", // 不生成输出文件 "target": "es6", // 支持es6语法 "checkJs": "true", // 打开会检查所有的js, 如果不需要可以手动的在需要检查的js文件头部加上 @ts-check的标记. }, "include": [ "src/**/*" ], "exclude": [ "node_modules", "**/*.spec.ts" ] } 复制代码
工作流集成
除开IDE和编辑器等开发 工具 的集成之外,我们还需要把TypeScript Checking JavaScript集成进我们的构建流程之中。TypeScript的CLI提供了非常强大的功能,由于在 tsconfig.json
中声名了只做类型检查,不做实际的编译,所以通过一条简单的 tsc
命令就能很好的帮助我们在构建中检查我们的代码是否存在构建错误。
一些限制
凡事都有两面性,Type Checking JS也并非没有缺点。在一段时间的试验后,我发现和直接编写TypeScript相比,Type Checking JS存在以下不爽的地方
1. 使用comments破坏代码语义化
比起类型声明和代码结合在一起,使用comments的形式难免在阅读和编写的时候感觉有些别扭,在代码上也有一定的冗余。
// ts 写法 let foo:string = (bar: string) => `${bar}` // type checking js写法 /** @type {(bar: string) => string} let foo = bar => `${bar}` 复制代码
2. 语法支持不统一
Webstorm出于某种原因并不支持typescript like的语法,我们只能退而求其次选择closure like的语法。 这让Type Checking JS的写法下降了不止一个档次。
以上所述就是小编给大家介绍的《使用Typescript给JavaScript做静态类型检查》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- python—静态类型检查
- 静态代码检查工具 cppcheck
- Flow 静态类型检查开发环境搭建
- Saluki: 使用静态属性检查查找污点风格的漏洞
- Mypy 0.740 发布,Python 静态类型检查工具
- React Native 工程中 TSLint 静态检查工具的探索之路
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Release It!
Michael T. Nygard / Pragmatic Bookshelf / 2007-03-30 / USD 34.95
“Feature complete” is not the same as “production ready.” Whether it’s in Java, .NET, or Ruby on Rails, getting your application ready to ship is only half the battle. Did you design your system to......一起来看看 《Release It!》 这本书的介绍吧!