typescript基础
typescript简介
typescript是javascript的一个超集,支持ES标准。在js的基础上通过类型注解,提供编译时的静态类型检查,可以编译成纯javascript代码,从而运行在浏览器与node上。
优势:
- 开发过程中,就发现潜在的问题。而非像js一样,执行才会报错
- 更友好的编辑器代码提示
- 代码语义更清晰易懂,无须深入代码逻辑
环境配置
- node环境
- 全局安装typescript:
npm install typescript -g,使用命令tsc编译ts文件 - 全局安装ts-node:
npm install ts-node -g,可直接运行ts文件
数据类型
类型分类
主要分为基础类型与对象类型,基础类型包括:null、undefined、boolean、number、string、symbol、void等,对象类型包括:函数、数组、对象等
// 基础类型
const personName: string = 'zhangsan';
const isMale: boolean = true;
const age: number = 18;
// 对象类型
class Person { }
const teacher: {
name: string,
age: number
} = { name: 'kahn', age: 19 }
const numbers: number[] = [1, 2]
const person: Person = new Person();
const getTotal: () => number = () => {
return 123
}
function getTotal2(): string {
return '123'
}
类型注解&类型推断
类型注解:显示的指定变量的类型。如:
let count: number;
count = 123;
类型推断:不指定变量的类型,直接对变量进行赋值。ts会自动的尝试分析变量的类型。如:
let count = 123;
简单的数据类型如基础类型,ts可自动识别出来的类型,可不使用类型注解,而自定义的数据结构如嵌套数组、对象、函数等,则最好使用类型注解。
函数类型相关类型
函数定义时,尽量将参数使用显示类型注解方式进行申明,而返回值不强制要求申明类型,看具体的情况决定。便于代码的阅读与报错检验,如:
function add1(num1: number, num2: number): number {
return num1 + num2;
}
function add2({num1, num2} : {num1: number, num2: number}): number { //解构类型参数的注解写法
return num1 + num2;
}
function string2num: (str: string) => number = (str) => {
return parseInt(str);
}
function sayHello(): void { //void表示函数没有返回值
console.log('hello');
}
function errorEmitter(): never { //never表示该函数没有办法执行完
throw new Error();
}
数组&元组
数组注解:
let arr1: number[] = [1,2,3];
let arr2: (number | string) = [1,2,'3'];
let arr3: {name: string}[] = [{name: 'zhangsan'}]
interface Person {name: string};
let arr4: Person[] = [{name: 'kahn'}];
type alias User {name: string};
let arr5: User[] = [{name: '张三'}]
class Teacher {name: string};
let arr6: Teacher[] = [{name: '王老师'}]
元组注解:(数组的长度与元素的类型固定时就可以使用元组)
let personInfo: [string, string, number] = ['kahn', 'male', 25];
let personInfos: [string, string, number][] = [
['kahn', 'male', 25],
['zhou', 'male', 25]
]
接口
注解形式:
interface Person {
name: string
}
const getPersonName = (person: Person) => {
return person.name;
}
const setPersonName = (person: Person, name: string) => {
person.name = name;
}
getPersonName({name: 'kahn', age: 12}); //会报错。以字面量的形式进行传递的时候,类型检查会比以变量进行缓存的方式更加严格
let person = {name: 'zhangsan', age: 18};
getPersonName(person); //不会报错
上述中的Person也可以用类型别名type定义:type Person = {name: string},效果是一样的。(但Interface只能定义对象类型,type还可以单独定义基础类型,如type name = string)。
如果需要在接口中的某些属性不是必须,则可以加上?修饰符,如:
interface Person {
name: string;
age?: number;
}
属性只允许读:
interface Person {
readOnly name: string
}
如果在接口中不确定是否需要在后期增加属性,可通过自定义属性方式,如:
interface Person {
name: string;
[proName: string]: any;
}
let person: Person = {name: 'kahn', class: '三年一班'};
接口中还可以定义方法:
interface Person {
name: string;
getName(): string;
}
let person = {name: 'kahn', getName: () => {return 'kahn'}}
class User implements Person { //类应用接口
name: 'zhangsan';
getName: () => {
return 'zhangsan'
}
}
上述中使用类来应用接口,此外,接口还可以进行继承,如:
interface Person {
name: string;
}
interface Teacher extends Person {
age: number;
}
// 上面将name这样的通性部分提出来,便于后续通性方法的使用(只需要增加子类接口的实现即可)
let getPersonName: string = (person: Person) {
return person.name;
}
接口也可以定义函数的类型申明,如:
interface sayHi {
(word: string): string;
}
let say: sayHi = (word: string) => {
return word;
}
类
定义与构造函数
typescript中类与ES6中的类比较相似,但ts中提供了更多的特性。基本定义:
class Person {
name: string; //ts中,需要提前定义类的属性,不像js中可以直接在this上通过"."或"[key]"的方式进行添加
constructor(name: string) {
this.name = name;
};
getName(): string {
return this.name;
}
}
class Teacher extends Person {
getName(): string {
return super.getName() + 'lee'; //当子类对父类中的方法重写时,而又需要用到父类方法时,可以使用super
}
}
let person = new Person('kahn')
let teacher = new Teacher('张老师');
console.log(person.getName(), teacher.getName());
上述类中的构造器也可以直接对参数进行访问修饰符,从而省略内部变量的定义,属于简化写法。如:
class Person {
constructor(public name: string) {
}
}
当父类中有构造函数时,子类需要在自己的构造函数中使用super实现父类的构造函数。即使父类没有构造器,子类也需要在构造器中调用空的super()进行实现。
访问权限
TS中增加了对类中变量、函数、构造方面的权限访问,包括:
public(默认):公有。可以在类中、类外访问。可以直接通过示例对象的属性访问private:私有。只允许在类中进行访问protected:受保护。可以在类中或子类访问
class Person {
public name: string;
private age: number;
protected sex: string;
}
class Teacher extends Person {
getName(): string {
return this.name + 'lee'
}
getAge(): string {
return this.age; //报错
}
getSex(): string {
return this.sex;
}
}
let person = new Person()
let teacher = new Teacher();
console.log(person.name);
console.log(teacher.name);
console.log(person.age); //报错
console.log(person.sex); //报错
getter与setter
class Person {
constructor(private _name: string) {} //私有属性一般加上下划线,便于后面的代码理解
get name() {
return this._name + 'xxx'; //通过添加尾部,或加密的方式,保护私有属性_name
}
set name(name: string) {
this._name = name;
}
}
let person = new Person('zhang')
console.log(person.name); //调用getter的时候,无需编写函数执行的形式
使用类实现“单例模式”:
class Person {
private static instance;
private constructor(private _name: string) {}; //不允许使用new创建对象
static getInstance(name: string) { //使用类的静态方法,在类中创建对象,并只允许新建一次
if (!this.instance) {
this.instance = new Person(name);
}
return this.instance;
}
get name(): string {
return this._name
}
}
let person1 = Person.getInstance('zhang');
let person2 = Person.getInstance('zhou');
console.log(person1.name); // zhang
console.log(person2.name); // zhang
抽象类与抽象方法
使用关键字abstract定义抽象类与抽象方法,如下:
abstract class Geom {
width: number;
getType(): string {
return 'geom'
};
abstract getArea(): number;
}
class Circle extends Geom {
getArea() {
return 123
}
}
抽象类不允许创建实例,只能用于继承。抽象方法无需在父类中进行实现,定义即可,而在子类中必须对抽象方法进行实现。
编译
写好的ts文件是不能直接拿来用的,除非使用ts-node。此时要进行tsc的编译过程。
搭建环境:
- 创建全局命令
tsc:npm install typescript -g - 项目中执行
npm init与tsc --init,前者是npm初始化生成package.json,后者是typescript配置初始化,生成tsconfig.json - 在package.json中增加
script命令:"build": "tsc",在tsconfig.json中设置编译后的文件路径outDir - 项目根目录中执行命令:
npm run build,即可在outDir定义的目录中查看到编译后的js文件
如果需要实时的监听ts文件的改动,并自动编译的话,在package.json中的build命令中,添加-w参数即可
再更一步需要编译后,自动执行,可以使用nodemon,使用npm install nodemon -D,然后在package.json中设置脚本"start": "nodemon ./build/xxx.js",然后控制台执行npm run start即可(注意nodemon是监听项目中所有文件的变化,包括文档,但不包括ts。如果需要忽略,则需要按照官方进行设置)
tsc -w可与nodemon在两个窗口之间配合使用,也可以使用concurrently将两个命令组合起来进行使用

浙公网安备 33010602011771号