JS是一门动态类型语言,在定义一个函数时,无法为其进行强类型指定,如:
function hello(name: string, content: string) {
// 如果name或content不是string类型的话,就抛异常
}
如果没有类型指定的话:
- 开发者常常不知道一个函数需要什么数据类型。
- 出现奇怪错误时,给debug造成麻烦。
其实业界已经有两种解决办法:
- 使用JSDoc对函数进行注释
- 使用强类型语言编程,最后编译成JS.
首先说第一种,JSDoc的语法规则可谓麻烦,注释简单类型时还稍微OK,如:
/**
* @param string name the name of the person
* @param string content the content to say
*/
function hello(name, content) { //... }
但如果我想对如下的数据结构做注释呢?
javascript
{ name: "jack", age: 18, address: { country: 'china', city: 'beijing' }, keywords: ['student', 'programmer', 'ios'] }
基本上没几个人能写的对JSDoc的注释,要对上述结构进行JSDoc,你需要:
- 艰难的Google它奇怪的语法。
- 写出来还很丑。
- 最后其它开发者也看不懂。
- 参数传错也没有错误提示。(WebStorm一定程度上可以进行类型推导)。
第二种,嗯,就不说了。
要想基本没有学习成本的进行类型声明和检查,下面进入正题,使用duckie.
安装
对于node/browserify/webpack的用户,直接:
npm install duckie
var t = require('duckie'); // go!
对于浏览器用户,可以直接使用https://github.com/ssnau/duckie/tree/master/build下已经编译好的文件,也可用bower安装。最后可以使用window.duckie
。
入门
回到篇首,如果想实现function hello(name:string, content:string)
该如何实现呢?
function hello(name, content) {
duckie.string.assert(name);
duckie.string.assert(content);
// 如果上面的断言不成立的话,将抛出异常
}
string
只是个示例,duckie总共支持如下一些基本类型:
- boolean/bool
- number
- string
- undefined
- null
- array
- object
- anything, 表示任意类型
即如下断言都为真:
duckie.boolean.assert(true);
duckie.number.assert(123);
duckie.string.assert('hello');
duckie.undefined.assert(undefined);
duckie.null.assert(null);
duckie.aray.assert([1,2,3]);
duckie.object.assert({name: 'jack'});
duckie.anything.assert('blabla');
如果只是断言简单的类型,那大可不必用duckie,JSDoc就基本能完成这种功效,除了不会抛异常。
duckie真正有效的地方在于,定义复杂的数据结构。
我们一个一个说起。
如果一个变量是枚举类型,如何限定它的枚举值呢?
使用oneOf
.
// 只有值为male或female的变量,才能通过认证
duckie.oneOf(['male', 'female']).assert('male') => true
duckie.oneOf(['male', 'female']).assert(1) => false
如果一个变量的类型,可能是undefined,可能是string,该如何表示?
使用maybe
。
duckie.maybe(String).assert('hello') => true
duckie.maybe(String).assert(undefined) => true
duckie.maybe(String).assert(123) => false
/*注:String可替换为duckie.string或"string",意义都一样*/
如果一个变量的类型可能是string,可能是number呢?
使用oneOfType
。
duckie.oneOfType([String, Number]).assert(1) => true
duckie.oneOfType([String, Number]).assert("hello") => true
duckie.oneOfType([String, Number]).assert(true) => false
如果一个变量是一个由数字组成的数组,该如何表示?
使用arrayOf(Number)
,或[Number]
.
// 使用arrayOf
duckie.arrayOf(Number).assert([1,2,3]) => true
// 直接使用[/*类型*/]
duckie([Number]).assert([1,2,3]) => true
duckie(['number']).assert(['hello', 'world']) => false
/* 注: 类型声明使用Number,duckie.number 和 'number' 效果是一样的。*/
如果一个变量是由一些key:value组成呢?
使用objectOf
,或[]
.
//例如定义一个Person数据结构,典型的变量如下:
var person = {
name: 'jack',
age: 18
};
duckie.objectOf({
name: String,
age: Number
}).assert(person) => true
duckie({
name: String,
age: Number
}).assert(person) => true
// 鸭子断言,即只要求被断言对象符合定义的
// 键值类型要求,而不要求精确匹配键数量
duckie({
name: String
}).assert(person) => true
duckie({
name: Number
}).assert(person) => false
如果一个变量是个object,里面有些值是数组呢?
以声明变量的方式用duckie声明你的类型。
// 比如篇首这东西
var person = {
name: "jack",
age: 18,
address: {
country: 'china',
city: 'beijing'
},
keywords: ['student', 'programmer', 'ios']
}
// 使用duckie声明
duckie({
name: String,
age: Number,
address: {
country: String,
city: String
},
keywords: [String]
}).assert(person) => true
声明一个类型跟声明一个对象般简单,完全没有学习成本。
总结
使用duckie可以像声明一个变量那样声明你的类型,且可以在运行时进行类型检查。如有什么建议,欢迎提议。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。