@ts-check

本文作者:IMWeb elvin 原文出处:IMWeb社区 未经同意,禁止转载

由于 JavsScript是弱类型,所以在大型项目中使用时显得能力略有不足。从七月份在腾讯实习到现在,接触到了不少项目的代码,平均算来每天都有 70% 的时间用于阅读、理解他人的代码。每次阅读他人代码的时候,我心中都会冒出来两个强烈的愿望:要是 JavaScript是强类型的多好!要是文档能再详细一点就好了!多亏了 TypeScript和 JSDoc,这两个愿望都有变成现实的可能。

@ts-check 立即上手

使用 TypeScript的最佳方式肯定是直接使用它的语法来编写 .ts 文件,然后通过编译器转换成 .js 文件。然而对于老项目而言,切换构建往往意味着麻烦和巨大的风险,而且假如将来 JavaScript也引入了类型系统(这非常有可能),那又得从 TypeScript切回 JavaScript(回归标准)。那么有没有一种无痛的方式,让我们既可以享受 TypeScript带来的好处,又能不改变项目的现有构建方式呢?

答案就是 // [@ts-check](/user/ts-check),在 .js 文件的头部引入这样一行注释,就可以使用 TypeScript了。

举个例子,在下图中我们首先声明了一个变量 a,然后把数字 1 赋给了它,接着又把字符串 '123' 赋给了它,看起来好像没有什么问题。

现在让我们加上// [@ts-check](/user/ts-check),咦,怎么 a 下面出现了红色的报错?把鼠标移到 a 处,发现报错是"Type '"123'" is not assignable to type 'number'",也就是说在 TypeScript中这种把字符串 '123' 赋值给数字变量 a 的做法是不妥的。

享受 TypeScript类型系统的好处就是这么简单,不需要改变构建,不需要进行项目的迁移,所需要做的仅仅是在 .js 文件的头部加入 // [@ts-check](/user/ts-check)(前提是你使用的是 VS Code,不过其它的编辑器下载相应的插件即可)。

JSDoc 添加类型

如果仅仅使用 // [@ts-check](/user/ts-check)的话,我们只能使用它的自动类型推断功能,这对于大型项目来说是远远不够的,我们希望能像强类型语言一样指定每个变量的类型。本着不对项目产生侵入的原则,TypeScript可以通过 JSDoc 风格的注释来完成这一点。接下来的举例说明取自官方的文档

/**
 * 使用 "@type" 来声明类型
 * @type {string}
 */
let var1;

/** @type {Window} */
let var2;

/**
 * 用 “return” 说明函数的返回值类型
 * @return {number}
 */
function fn1() {}

/**
 * 可以像使用 "@return" 一样使用 "@returns"
 * @returns {{a: string, b: number}}
 */
function fn2() {}

/**
 * 可以指定 union 类型,如字符串或者布尔值
 * @type {(string | boolean)}
 */
let var3;

/**
 * 声明元素类型是数字的数组 - 方式1
 * @type {number[]}
 */
let var4;

/**
 * 声明元素类型是数字的数组 - 方式2
 * @type {Array.<number>}
 */
let var5;

/**
 * 声明元素类型是数字的数组 - 方式3
 * @type {Array<number>}
 */
let var6;

/**
 * 声明对象类型
 * @type {{a: string, b: number}}
 */
let var7;

/**
 * 用 "@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;


/**
 * 声明函数参数类型
 * @param p0 {string} - TS 风格声明 p0
 * @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(p0, p1, p2, p3, p4){
  // TODO
}

/**
 * 也可以使用模板来声明类型
 * 如 fn4 表示返回值和参数 p1 是相同类型
 * @template T
 * @param {T} p1
 * @return {T}
 */
function fn4(p1){}

写在最后

对于老项目,使用 // [@ts-check](/user/ts-check) 和 JSDoc 引入 TypeScript来享受类型系统的好处是最简单、学习成本最低的方法。对于新项目,相较于激进地使用 .ts 文件,我认为 // [@ts-check](/user/ts-check) 和 JSDoc 是更好的方法,因为 JavaScript在不久的未来很有可能会引入可选的类型系统(类似于Python 3),到时候可以避免再从 TypeScript回归 JavaScript。

参考链接

  1. Type Checking JavaScript Files
  2. JSDoc support in JavaScript

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏趣谈编程

高并发下的HashMap

HashMap不是一个线程安全的类,在并发下可能会出现死循环(JDK1.7),今天我们来聊聊这个死循环是如何形成的

860
来自专栏偏前端工程师的驿站

前端魔法堂——异常不仅仅是try/catch

前言  编程时我们往往拿到的是业务流程正确的业务说明文档或规范,但实际开发中却布满荆棘和例外情况,而这些例外中包含业务用例的例外,也包含技术上的例外。对于业务用...

2617
来自专栏JAVA高级架构

Java 面试题:百度前200页都在这里了

基本概念 操作系统中 heap 和 stack 的区别 什么是基于注解的切面实现 什么是 对象/关系 映射集成模块 什么是 Java 的反射机制 什么是 ACI...

3606
来自专栏Web 开发

Backbone源码研究 – Backbone.Model

都因为 IE8 不支持 Object.defineProperty,但是业务还不能脱离 IE7 和 IE8,故研究下 Backbone.Model 的实现机制,...

620
来自专栏腾讯IVWEB团队的专栏

@ ts-check

每次阅读他人代码的时候,我心中都会冒出来两个强烈的愿望:要是 JavaScript是强类型的多好!要是文档能再详细一点就好了!多亏了 TypeScript和 J...

6190
来自专栏用户2442861的专栏

java IO流之一 IO流介绍

     IO流指 的是输入输出流,用来处理设备上的数据。这里的设备指硬盘,内存,键盘录入,网络传输等。

1003
来自专栏用户2442861的专栏

JavaScript Promise

在callback的模型里边,我们假设需要执行一个异步队列,代码看起来可能像这样:

1052
来自专栏极客编程

ECMAScript 6教程 (一)

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出 原文连接,博客地址为 http://www.cnblogs.co...

812
来自专栏nnngu

经典Java面试题收集

1、面向对象的特征有哪些方面? 答:面向对象的特征主要有以下几个方面: 抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面。抽象...

4726
来自专栏偏前端工程师的驿站

前端魔法堂——异常不仅仅是try/catch

1243

扫码关注云+社区