TypeScript
不是一个高深的技术,它不过是一个javascript
的超集,那么什么是超集呢?
所谓的超集 其实就是最终将你写的TypeScript
编译成javascript
去执行,由于浏览器上能跑的脚本语言是javascript
,这个本质要搞清楚javascript
Javascript
缺点:没法在编写时察觉出同一个变量的类型是否保持一致html
好比:前端
var a = 1 //若是这个b的值是“1”,字符串 var b = "1" console.log(a+b)
结果:java
特别是ES6
以前存在全局变量,var
会给全局状态下添加属性以及污染全局加上ES5
的变量提高做用域等混合状况,很容易致使变量查找时出现undefined
的问题,可是这个问题须要代码运行才能报错react
例如:webpack
var a; function test() { a = 1 } console.log(a) //undefined console.log(window.a)//undefined ------------------- var a; function test() { a = 1 } test() console.log(a) // 1 console.log(window.a) //1
像上面这种状况,若是遇到了,项目很大,排查起来仍是很烦的
特别是在书写Node.js
的时候,每每这种偏后台类型的代码,高并发场景出现一个小问题都是致命的,若是是一个超大型项目,排查问题起来很是困难es6
传统的javascript
web
这段代码,变量a
根本就没有定义,可是根本没有报错,这种场景能够在项目中多是右查询没有查询到,而后输出undefined. 但是若是是在使用这个变量去作某些事情typescript
例如: npm
这个a
变量是一个用户很核心的数据,可是它是undefined
。而后又通过若干的类型转换,被js
转换成不知道是什么的数据展现给了客户,那么炸了,可能会引发整个项目出现致命性错误直接奔溃
BUG
每每可能要浪费你们不少时间(摸鱼时间)例如 :
你的同事A
写了一个模块,大概5个文件,一共1000行代码
通过1000行代码的处理,最终输出好几个值(变量)给了你
以下代码:
export default { store, checkPassWord, applyMiddleWare, //.... }
一个不合格的同事 给你的没有注释的代码 因而你 :
一个合格的同事:
/** @params store //数据对象 @params checkPassWord //检查密码函数 @params applyMiddleWare //应用中间间 */ export default { store, checkPassWord, applyMiddleWare, //.... }
若是你用到他的暴露对象内容特别多的时候,就要一个一个去看注释,并且关键是:
这里面每一个函数的传入参数,返回的参数,注释不必定那么完整详细。
那么只有去沟通了,一旦沟通起来。时间成本上升,而且若是你们开发任务都特别紧急的时候,炸了~
TypeScript
出现了TypeScript 3.1
现已发布
最新版本文档地址 最新TypeScript版本文档地址
TypeScript
并不能说是一门彻底全新的语言,能够说它是一个基于javaScipt
的超集
什么是超集? 其实就是原生ES6
语法+Type
类型
强烈建议阅读阮一峰老师的 ES6入门
咱们来看下 TypeScript
的工做方式:
全局下载TypeScript
手动编译TS
文件变成js
文件
npm install -g typescript
用全局安装的typescript
来编译输出一把刚才的文件
尚未编译,如今已经开始报出问题,可是报出问题能够继续编译吗?
即便静态校验出现问题,最终仍是编译成功:
这里特别注意,TS
里面的静态类型,以及枚举等,编译成js
后是不存在的
上面并无体现typeScript
的特殊价值
TypeScript
的核心原则之一是对值所具备的结构进行类型检查。 它有时被称作“鸭式辨型法”或“结构性子类型化”。 在TypeScript
里,接口的做用就是为这些类型命名和为你的代码或第三方代码定义契约。
//接口名为LabelledValue interface LabelledValue { label: string; } //函数传入的参数 labelledObj遵循 LabelledValue接口 function printLabel(labelledObj: LabelledValue) { console.log(labelledObj.label); } let myObj = {size: 10, label: "Size 10 Object"}; printLabel(myObj);
以上代码通过ts
编译后,全部接口和静态类型都没有了 :
function printLabel(labelledObj) { console.log(labelledObj.label); } var myObj = { size: 10, label: "Size 10 Object" }; printLabel(myObj);
若是ts
在代码编写阶段出现了类型的校验错误,那么会直接提示:
我将接口的string
改为了number
类型
咱们仅仅改变了接口的类型,就马上检验到了错误,这样没必要等到开发模式下的热更新调试后再报错。
固然 你在接口定义时候,能够在变量后加上?
号
这样是一个可选属性
例如:
interface SquareConfig { color?: string; width?: number; } function createSquare(config: SquareConfig): {color: string; area: number} { let newSquare = {color: "white", area: 100}; if (config.color) { newSquare.color = config.color; } if (config.width) { newSquare.area = config.width * config.width; } return newSquare; } let mySquare = createSquare({color: "black"});
还有只读属性的接口定义:
interface Point { readonly x: number; readonly y: number; }
你能够经过赋值一个对象字面量来构造一个Point。 赋值后, x和y不再能被改变了。
let p1: Point = { x: 10, y: 20 }; p1.x = 5; // error!
用得比较多的函数类型检查
先编写接口
interface SearchFunc { (source: string, subString: string): boolean; }
定义函数
let mySearch: SearchFunc; mySearch = function(source: string, subString: string) { let result = source.search(subString); return result > -1; }
对于函数类型的类型检查来讲,函数的参数名不须要与接口里定义的名字相匹配。 好比,咱们使用下面的代码重写上面的例子:
let mySearch: SearchFunc; mySearch = function(src: string, sub: string): boolean { let result = src.search(sub); return result > -1; }
函数的参数会逐个进行检查,要求对应位置上的参数类型是兼容的。 若是你不想指定类型,TypeScript
的类型系统会推断出参数类型,由于函数直接赋值给了 SearchFunc类型变量。 函数的返回值类型是经过其返回值推断出来的(此例是 false和true)。 若是让这个函数返回数字或字符串,类型检查器会警告咱们函数的返回值类型与 SearchFunc接口中的定义不匹配。
let mySearch: SearchFunc; mySearch = function(src, sub) { let result = src.search(sub); return result > -1; }
鸭式辨形法,说的是:一个动物长得看起来像鸭子,叫起来也像鸭子,那么它就能够被认为是鸭子
定义类的类型:
interface ClockInterface { currentTime: Date; setTime(d: Date); } class Clock implements ClockInterface { currentTime: Date; setTime(d: Date) { this.currentTime = d; } constructor(h: number, m: number) { } }
一个接口能够继承多个接口,建立出多个接口的合成接口。
interface Shape { color: string; } interface PenStroke { penWidth: number; } interface Square extends Shape, PenStroke { sideLength: number; }
照本宣科写了这么多,其实这些就是TS
的最有用的地方。文档写得比较好,建议多去看几遍,前提是必定要学好ES6
!
TS
中必定要尽可能避免使用any
类型any
类型有太多不可预测的后果
function identity<T>(arg: T): T { return arg; }
咱们给identity
添加了类型变量T
。 T帮助咱们捕获用户传入的类型(好比:number),以后咱们就可使用这个类型。 以后咱们再次使用了 T当作返回值类型。如今咱们能够知道参数类型与返回值类型是相同的了。 这容许咱们跟踪函数里使用的类型的信息。
API
能够去刷文档,下面说重点:typescript
赶上了webpack
React
官方推荐使用typescript
使用传统的 react
脚手架
在 Create React App 中使用 TypeScript npx create-react-app my-app --typescript
切记 全部的ts
的依赖,都必须是@types
开头的 不然用不了
配置tsconfig.json
文件
{ "compilerOptions": { "outDir": "./dist/", "sourceMap": true, "noImplicitAny": true, "module": "commonjs", "target": "es5", "jsx": "react" }, "include": [ "./src/**/*" ] }
npm install --save react react-dom @types/react @types/react-dom
webpack.config.js
配置文件
module.exports = { entry: "./src/index.tsx", output: { filename: "bundle.js", path: __dirname + "/dist" }, devtool: "source-map", resolve: { extensions: [".ts", ".tsx", ".js", ".json"] }, module: { rules: [ { test: /\.tsx?$/, loader: "awesome-typescript-loader" }, { enforce: "pre", test: /\.js$/, loader: "source-map-loader" } ] }, externals: { "react": "React", "react-dom": "ReactDOM" } };
你们可能对externals字段有所疑惑。 咱们想要避免把全部的React都放到一个文件里,由于会增长编译时间而且浏览器还可以缓存没有发生改变的库文件。
TS
最基础关键的核心思想,已经介绍完了咱们不妨总结一下:
TS
最核心的优点 :
静态类型检查+校验,代码并无运行编译,就已经知道哪里有问题了,不管是变量查找仍是类型错误
TS
给咱们解决了什么问题
减小了开发沟通成本,打开你的代码就知道传入的是什么参数,返回什么参数。编译后代码量并无增长
TS
给咱们带来了什么麻烦
多写了不少接口,类型,一些快速开发的小项目感受用上更麻烦。若是是比较古老的js
插件第三方库,还用不了,要另想其余办法去支持。
大型项目,能够上ts
,仍是要上ts
,中小型项目,看工期,看你是否打算在时间容许状况下尝试使用ts
。
技术自己没有好坏,长远看,弱类型语言并非那么的友好。谷歌的Go
语言,写法就跟TypeScript
很像,若是想要拥有更广阔的技术视野,建议前端是能够从TS
学起,他们的思想大都差很少。
最后,欢迎你们加入咱们的segmentFault前端交流群
,个人我的微信是:CALASFxiaotan
,加我会拉你进群哦~
群里大把小姐姐等大家~
以为写得好,记得点个赞哦,永不脱发