前言
在之前我们已经了解了javaScript语言特征(类型),了解了静态类型有不少优点,合理运用可以让我们项目更加稳定健壮。
也入门了Flow(js类型检查工具)
这篇博客介绍下如何使用TypeScript(JavaScript超集语言)。
TypeScript是什么
TypeScript是微软公司开发的一款开源的JavaScript超集语言!
JavaScript超集: 当前任何JavaScript都是合法的TypeScript代码!
TypeScript主要为JavaScript提供了类型系统和ES6语法的支持!
TypeScript有自己的编译工具,我们写好的TypeScript代码最终会通过编译器编译成JavaScript代码进行运行!
Flow和TypeScript的区别
Flow是一个类型检查工具,TypeScript是一种开发语言!
如何使用
安装
TypeScript最终要运行起来,我们需要TypeScript代码转换成对应的JavaScript代码,那么TypeScript的命令行工具可以帮我们完成这件事情。
TypeScript的命令行工具安装方法(npm):
npm install -g typescript
安装好了之后,全局会提供一个tsc命令给我们使用!
编写ts代码
初体验
- 新建一个index.ts文件
- 写入简单例子
function hello(name:string){
console.log(name);
}
hello('小明');
- 执行编译
tsc ./index.ts
- 编译结果
//同目录下生成了一个index.js文件
function hello(name) {
console.log(name);
}
hello('小明');
- 再改个参数试试
function hello(name:string){
console.log(name);
}
hello(123);
- 在执行编译
tsc ./index.ts
提示以下报错?
index.ts:4:7 - error TS2345: Argument of type '123' is not assignable to parameter of type 'string'.
4 hello(123);
~~~
Found 1 error.
但是一看index.js文件还是被编译过来了
function hello(name) {
console.log(name);
}
hello(123);
我们发现
TypeScript 编译的时候即使报错了,还是会生成编译结果,我们仍然可以使用这个编译之后的文件。
如果要在报错的时候终止 js 文件的生成,可以在ts的配置文件: tsconfig.json 中配置 noEmitOnError 即可。
下面?就来介绍下ts的配置文件
tsconfig.json
创建配置文件
tsc --init
?常用配置项:
- target: 指的就是将ts代码要转换成哪个版本的js代码 es5 es3
- module: 指的就是将ts代码转换成js代码之后,使用的模块化的标准是什么
- outDir: 指的就是将ts代码转换成js代码之后,js代码存放的文件夹路径
- rootDir: 指的就是要将哪个目录中的ts代码进型转换,ts代码的存放路径
- strict: 是否要将ts代码转换为严格模式的js代码!
使用配置文件
- 不带任何输入文件的情况下调用tsc,编译器会从当前目录开始去查找tsconfig.json文件,逐级向上搜索父目录。
- 不带任何输入文件的情况下调用tsc,且使用命令行参数–project(或-p)指定一个包含tsconfig.json文件的目录。
tsc -p ./tsconfig.json
ts中的数据类型
// number
let a: number = 10;
let b: number = NaN;
let c: number = Infinity;
let d: number = 0xA12;
let e: number = 0b1010101;
let f: number = 0o75;
// string
let str: string = "这是一个字符串"
let str1: string = '这是一个字符串'
let str2: string = `hello 这是一个模板字符串${a}`
// boolean
let flag: boolean = true;
let flag1: boolean = false;
// 数组
// Array<数据类型>
let arr: Array<number> = [1, 2, 3, 4];
// 数据类型[]
let arr1: number[] = [1, 2, 3, 4];
// 元组(Tuple)
let arr2: [number, string] = [1, 'a'];
arr2[0] = 'a';//error
arr2[0] = 1000;//work
arr2[2] = 'a';//work
arr2[2] = 1;//error
arr2[2] = [];//error
// void 空值
let res: void = undefined;
// undefined
// null
let res1: undefined = undefined;
let res2: null = null;
// any 表示任意类型
let somevar: any = 10;
somevar = "abc";
somevar = [];
// never类型
// never类型一般用在不可能返回内容的函数的返回值类型设置
function test(): never{
while (true) {
}
}
// object类型
// let o: object = {};
// let o1: object = [];
// 对象类型
let o: { name: string, age: number } = { name: "张学友", age: 18 };
// enum: 枚举类型
// gender: 0 1 -1
enum Gender{
male = 1,
female = 0,
unknow = -1
}
let gender: Gender = Gender.male;
let obj = {
gender: Gender.male
}
// 类型断言
//类型断言(Type Assertion)可以用来手动指定一个值的类型
//语法
/*<类型>值
或
值 as 类型*/
//例子:将一个联合类型的变量指定为一个更加具体的类型
function getLength(something: string | number): number {
if (something.length) {
return something.length;
} else {
return something.toString().length;
}
}
//上例中,获取 something.length 的时候会报错。
//此时可以使用类型断言,将 something 断言成 string:
function getLength(something: string | number): number {
if ((<string>something).length) {
return (<string>something).length;
} else {
return something.toString().length;
}
}
ts中的类
不太了解es6中的类的可以去看下这篇文章:简书:es6中class类的全方面理解(一)
class Person{
// 和ES6不同的是,TS中属性必须声明,需要指定类型
name: string
// 声明好属性之后,属性必须赋值一个默认值或者在构造函数中进行初始化
age: number
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
sayHello(msg: string): void {
console.log(msg);
}
}
ts中类的继承
class Animal{
age: number
constructor(age: number) {
this.age = age;
}
eat() {
console.log("吃个大鸡腿儿")
}
}
class Dog extends Animal{
type: string
constructor(type: string, age: number) {
//相当于es6中的call借用方法
super(age);
this.type = type;
}
// 子类中如果出现了和父类同名的方法,则会进行覆盖
// 也就是调用的时候,调用的就是子类中的方法了!
eat() {
console.log('狗对象中的eat方法')
}
}
var dog = new Dog("哈士奇", 18);
dog.eat();
ts类中的访问修饰符
// 访问修饰符:
// 指的就是可以在类的成员前通过添加关键字来设置当前成员的访问权限
// public: 公开的,默认 所有人都可以进行访问
// private: 私有的, 只能在当前类中进行访问
// protected: 受保护的,这能在当前类或者子类中进行访问
enum Color{
red,
yellow,
blue
}
class Car{
// 如果不加访问修饰符 则当前成员默认是公开的 所有人都可以访问的
public color: Color
constructor() {
this.color = Color.red;
this.run();//work
this.loadPeople();//work
}
// 加了private之后,当前成员就只能在当前类中使用了!
private run() {
}
// 加了protected之后,当前成员就只能在当前类或者子类中使用了!
protected loadPeople() {
}
}
let c1 = new Car();
c1.color
c1.run();//error
c1.loadPeople();//error
class Audi extends Car{
sayHi() {
console.log(this.color)
this.run();//error
this.loadPeople();//work
}
}
let audi = new Audi();
audi.color;
audi.run();//error
ts的只读属性和参数属性说明
class Cat{
// 如果给属性添加了readonly修饰 则这个属性无法被赋值
// 而且属性必须在声明的时候或者在构造函数中被赋值!
readonly name: string
// type: string
// 构造函数中给参数前面加上修饰符,就相当于声明了一个属性!
constructor(public type: string) {
this.name = "加菲"
// this.type = type
}
}
var cat = new Cat("橘猫");
// cat.name = "123"
// cat.type;
ts中类成员的存取器
class People{
// name: string = ""
private _name: string = ""
// 属性的存取器
get name(): string{
return this._name;
}
set name(value: string) {
// 设置器中可以添加相关的校验逻辑
if (value.length < 2 || value.length > 5) {
throw new Error("名字不合法,不许使用!")
}
this._name = value;
}
}
var p = new People();
p.name = "爱新觉罗PDD"
console.log(p.name);
ts中的接口(相当于一种规范)
interface
// 接口使用interface进行声明
interface AjaxOptions{
url: string,
// 给属性加上?之后,这个属性就是可选的!
type?: string,
data?: object,
success(data: object): void
}
// option参数中 需要包含 url type data success
function ajax(options: AjaxOptions) {
}
ajax({
url: "http://www.baidu.com",
type: "get",
data: {},
success(data) {
}
})
ts中的额外属性检查
interface Point{
readonly x: number,
y: number,
[propName: string]: any
}
let poi: Point = {
x: 10,
y: 10
}
// poi.x = 100;
//传入额外属性z
let poi1: Point = {
x: 10,
y: 10,
z: 100
}
函数类型的接口
interface SumInterFace{
(a: number, b: number): number
}
let sum: SumInterFace = function (a: number, b: number) {
return a + b;
}
类类型的接口
implements
interface PersonInterFace{
name: string,
age: number,
eat():void
}
class XiaoMing implements PersonInterFace{
name: string = "小明";
age: number = 18;
eat() {
}
}
接口的继承
接口继承接口
interface TwoDPoint{
x: number,
y: number
}
interface ThreeDPoint{
z: number
}
interface FourDPoint extends ThreeDPoint, TwoDPoint{
time: Date
}
let poi2: FourDPoint = {
z: 100,
x: 100,
y: 100,
time: new Date()
}
接口继承类
class Bird{
type: string = "画眉鸟"
fly():void {
}
}
interface Fly extends Bird{}
let flyingBird: Fly = {
type: "啄木鸟",
fly(): void {
}
}