前述
什么是TypeScript
TypeScript 是 JavaScript 的一个超集,主要提供了类型系统和对 ES6 的支持,同时它可以编译成纯 JavaScript,编译出来的 JavaScript 可以运行在任何浏览器上。
可以简单理解为 TS 就是 ES6 + 类型
TypeScript
的优点
- 强类型语言增加了代码可读性和可维护性,可以在编译阶段就发现大部分错误
- 增强了编辑器和 IDE 的功能,包括代码补全、接口提示、跳转到定义、重构等
- 很好的包容性,
.js
文件可以直接重命名为.ts
文件,并且即使 TypeScript 编译报错,也可以生成 JavaScript 文件- 兼容第三方库,即使第三方库不是用 TypeScript 写的,也可以编写单独的类型文件供 TypeScript 读取
准备
npm install typescript -g //用于将 ts 编译成 js
tsc --version //验证安装成功与否
类型
常见类型
/*布尔类型*/
let isDone: boolean = true;
/*数字类型*/
let count: number = 123;
/*字符串类型*/
let desc: string = "description";
let user = {name: "xiaoming", age: 18};
let desc: string = `hello, my name is ${user.name}, my age is ${user.age}`;
/*数组类型*/
let arr: Array<number> = [1, 2, 3];
let arr: number[] = [1, 2, 3];
/*元组类型*/
let tup: [string, number] = ['hello', 123];
/*Object类型(可以赋任意值,但是不能调用任意方法,即使它真的有)*/
//基本不用
let foo: object = {
name: "xiaoming",
age: 18
}
/*对象类型(解决object类型无法推断问题)*/
let user: {
name: string, //必须有
age: number //必须有
} = {
name: 'xiaoming',
age: 18
}
//1. 某个属性可有可无
let user: {
name: string,
age?: number
}
user = {name: 'aaa'}
//2. 只能确定某些属性,其他不知道有哪些
let user: {
name: string,
[key:string]: unknown //键:string;值:任意
}
user = {
name: 'aaa',
say() {
console.log(this.name)
}
}
if (typeof user.say === 'function') user.say()
/*接口(解决对象类型无法复用问题)*/
interface Person {
name: string,
age: number
}
let user: Person = {
name: 'xiaoming',
age: 18
}
/*any类型(可以回归弱类型用法,尽量少用)*/
let num: any = 10;
num = '20';
let ret: string = (num as string).length //如此即可提示出string的相关属性和方法
/*void(表示没有任何类型)*/
function bar(): void { //表示没有返回值
alert("hello typescript ~");
}
//声明一个void的变量,只能赋予undefined或null
let test: void = undefined;
let test: void = null;
/*null 和 undefined 类型*/
//和void一样,用于声明变量意义不大
let u: undefined = undefined;
let n: null = null;
//默认情况下undefined和null是所有类型的子类型,即可以将它们给如number类型赋值
//但是如果指定了 --strictNullChecks 标记,它们只能赋值给 void 以及它们自身。
/* unknown:表示一个未知类型 */
//1. 声明与基本用法
let a: unknown
a = 1
a = true
a = 'hello'
//2. 赋值
let a: unknown = '123'
let b: string
b = a //报错,指定了类型后,虽然字面上都是string,但无法这样直接赋值
if (typeof a === 'string') b = a //这样就可以
b = a as string //这样也可以
字面量声明
//字面量:客观存在的无法改变的值
//如:1,2,3,true,'hello'
let num: 23 //相当于const num = 23,即使用字面量声明后 num 的值为常量23
Enum
类型
enum sex {
MAN, WOMAN
}
console.log(sex.MAN) //0,默认第一个常量赋值为0,后面常量自增【同C语言】
enum sex {
MAN = 3, WOMAN
}
console.log(sex.WOMAN) //4
enum sex {
MAN='男', //非数字情况下,必须所有枚举值都要进行赋值
WOMAN='女'
}
联合类型声明
/* 用 | 进行联合类型声明 */
//1.表示param可以是这几种类型中的任意一种
let param: number | string | boolean
param = 123
param = '123'
param = true
//2.用于字面量
let param:12|13|14
param = 12
param = 13
param = 14
类型别名
type type1 = 1|2|3
let a: type1
let b: type1
解构
/*数组解构*/
let input = [1, 2]; //会自动进行类型推断(返回值也可以类型推断)
let [first, second] = input; //相当于 first=input[0]; second=input[1]
//交换变量
[first, second] = [second, first]; //相当于 let temp = first; first = second; second = temp;
//参数解构
function f ([first, second]: [number, number]) {
console.log(first);
console.log(second);
}
f([1, 2]);
//剩余参数解构
let [first, ...rest] = [1, 2, 3, 4, 5]
console.log(first) //1
console.log(rest) //[ 2, 3, 4, 5 ]
//忽略其他参数
let [first] = [1, 2, 3, 4, 5]
console.log(first) //1
//跳过一些参数
let [, second, , fourth, ] = [1, 2, 3, 4, 5]
console.log(second) //2
console.log(fourth) //4
//数组展开操作符
let arr1 = [1, 2, 3]
let arr2 = [...arr1, 4, 5, 6] //1, 2, 3, 4, 5, 6,实际是转换成了 concat 操作
/*对象解构*/
let o = {
a: "foo",
b: 12,
name: "bar"
}
let {b, name: c} = o //name是关键字,这里重命名为c
console.log(b, c) //12 bar
//剩余成员
let o = {
a: "foo",
b: 12,
c: "bar"
}
let {a, ...others} = o
console.log(a, others.b + others.c.length) //foo 15
//默认值
function f(o: {a: string, b?: number}) {
let {a, b = 1002 } = o;
}
//对象展开操作符
let o2 = {
...o,
d: 90,
e: ""
}
类
基本用法
/*原本构造函数写法*/
function Person(name: string, age: number) {
this.name = name;
this.age = age;
}
Person.prototype.sayHello = function(): void {
console.log(this.name, this.age)
}
let p = new Person("张三", 19)
p.sayHello()
/*ES6写法*/
class Person {
name: string;
age: number;
constructor(name: string, age: number) { //类的构造函数(new时会自动调用)
this.name = name;
this.age = age;
}
sayHello(): void {
console.log(this.name, this.age);
}
}
let p = new Person("张三", 19);
p.sayHello();
类的继承
class Person {
name: string;
age: number;
constructor(name: string, age: number) { //只能有一个构造函数
this.name = name;
this.age = age;
}
sayHello(): void {
console.log(this.name, this.age);
}
}
class Student extends Person {
constructor(name: string, age: number) {
super(name, age);
}
}
new Student("小明", 19).sayHello();
简写方式
class Person {
name: string;
age: number;
sex: number;
constructor(name: string, age: number, sex: number) {
this.name = name;
this.age = age;
this.sex = sex;
}
}
//等价于以下的简写方式(可混写):
class Person {
sex: number;
constructor(public name: string, public age: number, sex: number) {
this.sex = sex; //混写
}
}
getter & setter
class Person {
/**
* 1. 注意需要在属性前加上 _
* 2. !:非null和非undefined的类型断言
*/
private _name!: string;
get name() {
return this._name;
}
set name(name: string) {
this._name = name
}
}
let person = new Person();
person.name = "小明" //set方法
console.log(person.name) //get方法
修饰符
修饰符书写有先后顺序:访问 -> 静态 -> 只读
访问修饰符
public:公开的,谁都能用(默认public)
protected:受保护的,仅类和类的子类能使用
private:私有的,仅类中才能使用(无法被继承)
静态修饰符
static:通过static修饰的成员叫静态成员,静态成员无需实例化,直接通过类名调用
只读修饰符
readonly:表示只可读,不可写(作用和const修饰的常量类似)
/*
1. 可以在声明同时赋予初始值
2. 可以在构造函数中赋值或者修改初始值
*/
class foo {
public readonly desc: string = 'this is a demo.'
}
函数
参数与返回值
function demo(x: number, y: number): number {
return x + y
}
/* 返回值: void */
//可以返回 空、null、undefined
/* 返回值: never */
//什么都无法返回
可选参数
function demo(x: number, y?: number): number {
return x + 10
}
默认值
function add(x: number, y: number = 10) {
return x ** 2 + y;
}
console.log(add(3)) // 3*3 + 10 = 19
console.log(add(3, 20)) //3*3 + 20 = 29
可变参数
function add(...nums: number[]) {
return nums.reduce((previous, current) => previous + current);
}
let sum = add(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
console.log(sum) //55
箭头函数
let add = (x: number, y: number): number => x + y
循环
for
同 js
for (let i = 0; i < 5; i++) { console.log(i) }
forEach
不支持 break
[1, 2, 3].forEach((value, index) => { console.log(index, value) })
for in
会将数组当做对象来遍历
let arr: number[] = [1, 2, 3] for (const arrKey in arr) { console.log(arr[arrKey]) //1, 2 if (arr[arrKey] == 2) break }
for of
支持 break
let arr: number[] = [1, 2, 3] for (const number of arr) { console.log(number) //1, 2 if (number == 2) break }
模块
导出
export default xxx //导出默认成员
export const foo: string = 'bar' //导出指定成员
export const bar: string = 'bar' //导出指定成员
导入
import xxx from '模块标识' //导入默认成员
import {foo, bar} from '模块标识' //导入指定成员
tsconfig.json
自动编译
只要包含
tsconfig.json
文件,在该文件所在目录中执行tsc -w //w表示实时监控
,这样就会自动对该目录及各级子目录中所有的ts
文件编译为js
文件
配置选项
{
"compilerOptions": {
"allowJs": false, //是否对js进行编译,默认false
"checkJs": false, //是否检查js语法规范,默认false
"removeComments": false, //在编译时是否移除注释,默认false
"noEmit": false, //不生成编译后的文件(只进行语法检查),默认false
"noEmitOnError": false, //当存在语法错误时不生成编译后的文件,默认false
"alwaysStrict": false, //编译后的js文件是否启用strict严格模式,默认false
"noImplicitAny": false, //不允许隐式的any类型,默认false(function add(a, b){return a+b} //a和b即为隐式的any类型)
"strictNullChecks": false, //严格的检查空值,默认false
"target": "esnext", //编译后的js目标版本,可选[ES5 / ES2015, ES6 / ES2016, ES2017 / ESNext]
//指定要使用的模块化规范,可选[None, CommonJS, AMD, System, UMD, ES6等]
// - 其中只有 AMD和System 能和 --outFile 一起使用
// - 其中ES6和ES2015 可使用在目标输出为ES5或更低的版本的情况
"module": "esnext",
"strict": true, //所有严格模式的总开关,默认false(可控制如strictNullChecks、noImplicitAny、alwaysStrict等)
"jsx": "preserve",
"importHelpers": true,
"moduleResolution": "node",
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"sourceMap": true,
"baseUrl": ".",
"types": [
"webpack-env"
],
"paths": {
"@/*": [
"src/*"
]
},
//指定编译过程中需要引入的库文件列表
// - 如果没有指定,则根据不同的target,有以下默认值
// - - target ES5:DOM, ES5, ScriptHost
// - - target ES6:DOM, ES6, DOM.Iterable, ScriptHost
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
],
"outDir": "./dist", //指定编译后文件所在的目录(会自动创建)
"outFile": "" //将所有编译后的文件合成一个文件并输出(会自动创建)
},
"include": [ //需要编译的ts文件所在的目录,默认[**/**],**表示任意目录,*表示任意文件,a/**/*表示a下的所有文件
"src/**/*.ts",
"src/**/*.tsx",
"src/**/*.vue",
"tests/**/*.ts",
"tests/**/*.tsx"
],
"exclude": [ //不需要编译的目录,默认["node_modules", "bower_components", "jspm_packages"]
"node_modules"
],
"extends": "./config/base.json", //表示继承(包含)base.json中的所有配置信息,后缀可省略
"files": ["指定具体要编译的ts文件列表.ts"]
}