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@arg
or@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)项目 ...
随机推荐
- 物理CPU数、CPU核心数、进程数
参考CSDN博客:https://blog.csdn.net/helloworld0906/article/details/90547159 一. 物理cpu数.cpu核数.线程数(逻辑cpu数)的关 ...
- docker安装mysql,tomcat,并且在tomcat可以访问到mysql
1.uname -an 查看当前系统版本 2.yum -y install docker 下载安装docker 3.service docker start 启动docker服务 4.docker ...
- 问题 C: 「Usaco2010 Dec」奶牛健美操O(∩_∩)O
题目描述 Farmer John为了保持奶牛们的健康,让可怜的奶牛们不停在牧场之间的小路上奔跑.这些奶牛的路径集合可以被表示成一个点集和一些连接 两个顶点的双向路,使得每对点之间恰好有一条简单路径. ...
- Hibernate一对多、多对一的关系表达
一.关系表达: 1.一对多.多对一表的关系: 学生表: 班级表: 在学生表中,学生的学号是主键.在班级表中,班级号是主键,因此,学生表的外键是classno.因此,班级对应学生是一对多,学生对应班级是 ...
- html5 svg实现不规则形状图片触发事件
html5 svg实现不规则形状图片触发事件<pre><!DOCTYPE html><html lang="en"> <head> ...
- day1-python条件语句和基本数据类型
一.if 条件语句 1. if 条件语句 if 条件: 代码块 else: 代码块 2. if 支持嵌套 if 1 == 1: if 2 == 2: print("欢迎进入blog1&quo ...
- python文件的基本操作
打开文件的三种方式: open(r'E:\学习日记\python\code\文件的简单操作.py') open('E:\\学习日记\\python\\code\\文件的简单操作.py') open(' ...
- PHP Openssl 生成公钥私钥
<?php //配置信息 $dn = array( "countryName" => "GB", "stateOrProvinceName ...
- (C#)WPF:Property和Attribute的区别
在C#里Property是属性,Attribute是特性.它们的概念是不一样的,充其量就是中文的神翻译问题. 1)属性是指类体里用get或set封装好的属性.属性是面向对象的理论范畴.比如说一个盒子, ...
- Leetcode算法【114. 二叉树展开为链表】
上周通过一位小伙伴,加入了一个氛围很好的小群,人不多,但是大家保持着对知识的渴望,让我很感动. 我自己也有一个群,人数也不多,但是能真正互动起来一起学习,一起进步的,还是太少.所以,现在也在学习如何让 ...