JS的静态类型检测,有内味儿了
我们知道 TypeScript 2.3 以后的版本支持使用--checkJs对.js文件进行类型检查和错误提示。 但是由于 JavaScript 是弱类型语言,在编写代码的时候,是无法检测变量的类型的。
因此每次运行代码类型报错的时候,我心中都会冒出来一个强烈的愿望:要是 JavaScript是强类型的多好!
好消息是,JSDoc 的 @ts-check,可以现实这个愿望。
立即上手
如果能有机会使用 TypeScript 那当然是最好,但是往往开发的老项目在早期都是 JavaScript 完成的,如果都迁移到 TypeScript 版本工作量是庞大的,而且不可避免出现许多bug问题,那么有没有一种方式可以无痛的在使用JavaScript的同时享受到TypeScript的类型检查呢?
答案就是 // @ts-check,在 js 文件的头部引入这样一行注释,然后配合JSDoc就可以在JavaScript代码中使用 TypeScript的类型检查了。
举个例子,在下图中我们首先声明了一个变量 a,然后把数字 1 赋给了它,接着又把字符串 '1' 赋给了它,看起来好像没有什么问题,而且运行起来也不会报错。
let a = 1;
a = 'a';
然后我们加上 // @ts-check 试试:
// @ts-check
/**
* @type {Number}
*/
let a = 1;
a = '1';
神奇的一幕出现了,在变量a赋值的下面,出现了红色波浪线,鼠标放上去提示:
let a: number
@type — {Number}
不能将类型“"1"”分配给类型“number”。ts(2322)

也就是说我们将一个字符串赋值给了一个数字类型的变量是有问题的,这个时候我们未运行程序,但是编辑器已经帮我们分析出了代码可能存在的问题,这时候我们运行代码,是没有报错的。
因为这个类型检测只是让我们按照TypeScript的强类型语言检测类型问题,但是我们依然是JavaScript代码依然会按照JavaScript的代码逻辑运行,如是TypeScript代码的话,这里运行就会报错。
JSDoc 类型标记
既然ts-check这么好用,我们来看看 JSDoc 类型的注释支持哪些类型的检测。
根据官方文档,JSDoc现在支持下面几个类型检测:
@type@param(or@argor@argument)@returns(or@return)@typedef@callback@template@class(or@constructor)@this@extends(or@augments)@enum
下面我们选择常用的标记进行说明,更多更详细的标记可以参考官方文档。
@type
描述:用来声明变量的类型。
/**
* - string类型
* @type {string}
*/
let a1;
/**
* - windows对象类型
* @type {Window}
*/
let a2;
/**
* - string或者boolean类型
* @type {string | boolean}
*/
let sb;
// -------- 多种方式指定数组类型--------
/** @type {number[]} */
var ns;
/** @type {Array.<number>} */
var nds;
/** @type {Array<number>} */
var nas;
// ---- 还可以指定对象字面量类型。 例如,一个带有a(字符串)和b(数字)属性的对象---
/** @type {{ a: string, b: number }} */
var var9;
@param和@returns
描述:@param语法和@type相同,但增加了一个参数名。
/**
* 声明函数参数类型
* @param {string} p1 - p1 是 string 类型参数
* @param {string=} p2 - p2 是可选的 string 类型参数
* @param {string} [p3] - 另外一种可选参数写法
* @param {string} [p4="test"] - p4 是可选的 string 类型参数(默认值为 "test")
* @return {string} - 函数返回值是 string 类型
*/
function fn3(p1, p2, p3, p4){
// TODO
}
/**
* 用 “return” 说明函数的返回值类型
* @return {number}
*/
function fn1() {}
/**
* 可以像使用 "@return" 一样使用 "@returns"
* @returns {{a: string, b: number}}
*/
function fn2() {}
@typedef
描述:@typedef 可以用来声明复杂类型,和@param类似的语法。
/**
* 用 "@typedef" 自定义复杂类型
* @typedef {Object} SpecialType - 创建一个新的类型 'SpecialType'
* @property {string} prop1 - SpecialType 属性 prop1 是 string 类型
* @property {number} prop2 - SpecialType 属性 prop2 是 number 类型
* @property {number=} prop3 - SpecialType 属性 prop3 是可选的 number 类型
* @prop {number} [prop4] - SpecialType 属性 prop4 是可选的 number 类型
* @prop {number} [prop5=42] - SpecialType 属性 prop5 是可选的 number 类型(默认值 42))
*/
/** @type {SpecialType} */
let specialTypeObject;
可以在第一行上使用
object或Object。
实验要求
经测试,在 VSCode 和 IDEA下可以直接使用ts-check 的类型检测,sublime等编辑器不可以,应该是要下载对应的插件才可以。
写在最后
对于老项目,使用 // @ts-check 和 JSDoc 来来享受TypeScript类型系统的好处是最简单、学习成本最低的方法。
而对于新项目,则更加推荐直接使用 TypeScript 来进行代码编写,并且各大框架里面都是用的TypeScript进行的代码编写,在可期的未来,TypeScript将会越来越受欢迎。
JS的静态类型检测,有内味儿了的更多相关文章
- 【JS】类型检测
本文首发于我的个人博客 : http://cherryblog.site/ 前言 js 中的类型检测也是很重要的一部分,所以说这篇文章我们就来讲一下怎么对 JavaScript 中的基本数据类型进行检 ...
- JS中 typeof,instanceof类型检测方式
在js中的类型检测目前我所知道的是三种方式,分别有它们的应用场景: 1.typeof:主要用于检测基本类型. typeof undefined;//=> undefined typeof 'a' ...
- JS中类型检测方式
在js中的类型检测目前我所知道的是三种方式,分别有它们的应用场景: 1.typeof:主要用于检测基本类型. typeof undefined;//=> undefined typeof 'a' ...
- JS做类型检测到底有几种方法?看完本文就知道了!
JS有很多数据类型,对于不同数据类型的识别和相互转换也是面试中的一个常考点,本文主要讲的就是类型转换和类型检测. 数据类型 JS中的数据类型主要分为两大类:原始类型(值类型)和引用类型.常见的数据类型 ...
- JS 类型检测
typeof 适合函数对象和基本类型的判断 typeof 100instanceof 适合判断对象类型 obj instanceof Object 基于原型链判断操作符,若做操作符不是对象,则会直接返 ...
- boost学习 内嵌类型检测 与 any 的代码练习
本文是学习 boost源码的一些练习 参考文章来自 刘未鹏 C++的罗浮宫(http://blog.csdn.net/pongba) 目录 http://blog.csdn.net/pongba/ar ...
- js安全类型检测
背景: 都知道js内置的类型检测,大多数情况下是不太可靠的,例如: typeof . instanceof typeof 返回一个未经计算的操作数的类型, 可以发现所有对象都是返回object ...
- JS数组类型检测
在强类型语言,数组类型检测是非常容易的事情(typeof就可以解决),而在弱语言JS数据类型就很容易混淆了. JS中常见的数据类型有:number.string.boolean.undefined.f ...
- flow 静态类型检查 js
1.flow介绍 https://ustbhuangyi.github.io/vue-analysis/prepare/flow.html#为什么用-flow 2.使用 (1)安装flow (2)项目 ...
随机推荐
- Oracle“ORA-00979:不是GROUP BY 表达式”解决方式
今天在工作中碰到一个问题,用group by 语句进行分组时出现ORA-00979错误. 代码如下: select R.ORDER_NO, R.PRODUCT_CODE, R.REGION_NO, R ...
- windows下同时装了Python3和Python2,如何区分使用?
1.前言 想学习Python3,但是暂时又离不开Python2.在Windows上如何让它们共存呢? 目前国内网站经常会让大家把其中一个python.exe改个名字,这样区分开两个可执行文件的名字,但 ...
- python接口测试-数据驱动-DDT
DDT是python的第三方库,全名称为:Data-Driven/Decorated Tests. ddt安装 通过pip安装ddt模块,安装Python后,Python自带pip功能包 切换到Pyt ...
- dubbo中出现can not be invoked any more
具体错误示例如下 从错误看,是客户方发起调用时,dubbo会去检查本地的invoker instance,如果发现invoker已经是destroy status,则直接抛出上面的异常,下面先来说下平 ...
- jsp页面时间的转换js
/** * 日期 转换为 Unix时间戳 * @param <string> 2014-01-01 20:2 ...
- 修改 Django Administration
只需要在django项目下的APP下的admin.py重写以下几个变量即可,不需要改django源码 from django.contrib import adminadmin.site.site_t ...
- [Error]使用了未经检查或不安全的操作...
编译错误注: MethodReflect.java使用了未经检查或不安全的操作.注: 有关详细信息, 请使用 -Xlint:unchecked 重新编译. 解决:在类前面加入下面一句解决 @Suppr ...
- JS如何在不给新空间的情况下给数组去重?
1.先排序,在让相邻元素对比去重 const nums = [3, 1, 1, 5, 2, 3, 4, 3, 5, 5, 6, 4, 6, 6, 6]; Array.prototype.arrayNo ...
- 领扣(LeetCode)删除链表的倒数第N个节点 个人题解
给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点. 示例: 给定一个链表: 1->2->3->4->5, 和 n = 2. 当删除了倒数第二个节点后,链表变为 ...
- Python 之路 Day01 笔记-什么是变量,常量等
变量 变量 是 为了存储 程序运算过程中的一些中间 结果,为了方便日后调用 变量的命名规则 1. 要具有描述性 2. 变量名只能'_','数字','字母'组成,不可以是空格或特殊字符(#?<., ...