Typescript是JavaScript的超集;任何JavaScript环境都支持,最低可以编译到es3;被称为前端领域中的第二语言
1 开始
安装 yarn init 然后 yarn add typescript
安装完成后编译 yarn tsc tsname.ts
完成后生成一个同名的js文件
或者执行yarn tsc —init,会生成一个tsconfig.json文件,项目中执行yarn tsc,会按照配置编译整个项目
2 ts中的原始数据类型
const a: string = 'jason';const b: number = 200;const c: boolean = true;const d: null = null;const e: void = undefined;const f: undefined = undefined;const h: symbol = Symbol();
3 TS中的标准库,标准库就是内置对象所对应的声明文件;
如果tsconfig.json中的target定位为es5,意味着代码会编译到es5;
此时如果ts中的原始数据赋值为Symbol()时就会报错;两种解决方法,一种是直接改tsconfig中的target为es2015;另外一种,改tsconfig中的lib选项,数组中添加es2015;
第二中方法lib数组中只有es2015则会覆盖所有的默认标准库,比如代码中有console命令就会报错;在typescript中dom和bom标准库统一为DOM,此时在lib数组中再追加DOM就就可以解决问题了;
4 TS编译时的错误提示,换成中文的小技巧:
在执行tsc命令后面添加 —locale zh-CN;vscode中添加错误提示时用中文的技巧,在vscode中搜索配置,typescript locale选择zh-CN
5 作用域问题
两个ts文件,如果没有模块导出,则定义同名变量的时候会提示报错,因为默认作用域是全局;解决方法就是通过export语法,定义单个ts文件为模块,它里面的作用域就是模块内部的作用域了
6 typescript中的object类型
ts中object 类型不单指对象,包括对象、数组、函数;如果类型是object而接受原始类型则报错;
const aa: object = function(){};const bb: object = [];const cc: object = {a: 1};// const dd: object = true; // 报错// 定义普通对象类型是要熟悉和值类型必须一致,不能少也不能更多 更专业的用interfaceconst ee: {a: string, b: number } = {a: '1', b: 2}export {}
7 typescript中的数组类型
// 数组类型const arr1: Array<number> = [1,2,3]const arr2: number[] = [1,2,3]//function sum(...args: number[]) {return args.reduce( (prev, current) => prev + current, 0)}sum(1,2,3,'ss') // ss会标记错误
8 typescript中的元组类型
// 元组// 多或者少赋值都会报错const tuple: [string, number] = ['1',2]// 可以用数组下标获取const age = tuple[0]const name = tuple[1]// 也可用数组解构取值const [a,b] = tuple;// 一般用来返回函数固定格式值export {}
9 typescript中的枚举类型
// 枚举类型// 指定值enum PostStatus {Draft = 0,Unpublished = 1,Published = 2}// 不指定值,默认从0开始累加enum PostStatus1 {Draft,Unpublished,Published}// 如果给第一个成员指定初始值,后续成员以此为基础累加enum PostStatus2 {Draft = 3,Unpublished,Published}// 字符串枚举则必须每个成员都设置初始值enum PostStatus3 {Draft = 'sss',Unpublished = 'sfsf',Published = 'sfs'}// 枚举类型编译后会入侵代码// PostStatus[0] => draft// 通过const添加的枚举值会在编译的时候移除枚举类型,并替换成对应的值const enum PostStatus4 {Draft = 'sss',Unpublished = 'sfsf',Published = 'sfs'}//使用枚举类型const post = {status: PostStatus4.Draft}export {}
10 typescript 中的函数类型
// 函数类型// --------------函数声明// 默认值function fn1(a: string, b: string, c: number = 10) {return a + '-----' + b}// 可选参数function fn2(a: string, b: string, c?: number) {return a + '-----' + b}// 任意个数参数function fn3(a: string, b: string, ...rest: number[]) {return a + '-----' + b}// fn1(10,200) // 报错// fn1('ajson','tom','fsf')// 报错fn1('ajson','tom')// fn1(10,200) // 报错// fn1('ajson','tom','fsf')// 报错fn1('ajson','tom')// --------------函数表达式const fn4: (a: number, b: number) => string = function(a, b) {return `hello ${a}, hello ${b}`}export {}
11 typescript中的任意类型
// any类型// 动态类型,可以接受任意类型参数function stringify(value: any) {return JSON.stringify(value);}stringify('string')stringify(200)stringify({a:1})// 重新赋值其他类型的值let foo: any = 'str';foo = 100;foo.fn();export {}
12 隐式类型推断
// 隐式类型推断const age = 18;// age = 'sss';// 报错// ts无法推断类型时,会标记为anylet fn; // let fn: any;export {}
13 断言
// 类型断言export { }const arr = [20, 30, 40, 50];const num = arr.find(i => i>20);// const square = num * num; // 虽然已知类型了,但是ts会报错// 用断言来解决const num1 = num as number;const num2 = <number>num; // jsx中会与标签产生冲突// 断言不是转换,在编译环节发生
14 typescript接口interface
// 接口interface Student {name: stringage: numbersex: stringnation: stringmarried?: boolean // 可选成员readonly level?: number // 只读成员}function getStudent(student: Student) {console.log(`${student.name}`)console.log(`${student.age}`)console.log(`${student.sex}`)console.log(`${student.nation}`)}//接口用来约束对象的结构,对象要实现接口就必须拥有接口的所有成员const info = {name: 'Jason',age: 18,sex: 'male',nation: 'hans',};// info.level = 10; // 报错getStudent(info)// 动态成员interface School {[prop: string]: string}const highSchool: School = {}highSchool.createDate = '1990-00-00';// highSchool.rebuildDate = 222;// 报错export {}
15 typescript中的类
es6以前都是用函数和原型来描述对象的特征属性,es6以后引入了class;
// classclass Person {public name: string; // public 默认是公有成员age: number = 18; // 构造函数赋值或者初始化赋值必须二选一private readonly score: number = 60; // 私有成员只能内部访问,readonly以后内部或者外部都不可修改protected site: string = 'r1l2' // 只能是内部或者子类访问constructor(name: string, age: number) {this.name = name;this.age = age;}sayHi(msg: string):void {console.log(`hello there, I am ${this.name}`)}}// 相比于js中的class,类的属性在使用之前必须先声明class Students extends Person {constructor(name: string, age: number){super(name, age);console.log(this.site) // protected属性可以在子类访问}}class NO1Students extends Person {// 通过private私有化构造函数,外部将无法通过此类进行实例化// 如果用protected修饰,则外部不可实例化,但是可继承private constructor(name: string, age: number){super(name, age);console.log(this.site) // protected属性可以在子类访问}// 此时只能通过静态方法来实例化,暴露给外部static getNo1(name: string, age: number) {return new NO1Students(name, age)}}const tom = new Person('Tom', 20);// console.log(tom.score) // 私有属性会报错const jason = NO1Students.getNo1('Jason', 18)
16 类和接口
// 类和接口export { }// 多个类有共同点时用interface来抽象interface Animal {eat(food: string): void;sleep(where: string): void;}class Dog implements Animal {eat() {}sleep() {}}class Cat implements Animal {eat() {}sleep() {}}// 推荐更简单的接口减少耦合interface Eat{eat(food: string): void;}interface Sleep{sleep(food: string): void;}class pets implements Eat, Sleep {eat() {}sleep() {}}class person implements Eat, Sleep {eat() {}sleep() {}}
17 抽象类
抽象类有地类似接口,但是不同于接口,抽象类可以有一些具体的实现
// 抽象类export { }abstract class Pets {eat(food: string): void {console.log(`I like to eat-----`)}abstract run(legs: number): void; // 抽象方法不需要方法体}// 抽象类只能被继承,不能用new关键词实例化class Dog extends Pets {// 必须实现抽象方法run(legs: number) {console.log(`I run by my ${legs} legs`)}}const dog = new Dog()dog.eat('火腿')dog.run(4)
18 泛型
// 泛型function createNumberArray(length: number, value: number): number[] {const arr = new Array<number>(length).fill(value);return arr;}function createStringArray(length: number, value: string): string[] {const arr = new Array<string>(length).fill(value);return arr;}// 泛型参数 createArray<T>中的Tfunction createArray<T>(length: number, value: T): T[] {const arr = new Array<T>(length).fill(value);return arr;}const createStr = createArray<string>(3, '20'); // [20,20,20]
19 类型声明
// 类型声明// 引入外部的js时,如果没有类型声明文件就安装@types/类型 ,如果还没有就自己声明一个类型import { camelCase } from 'loadsh';import qs from 'query-string';// declare function camelCase(params:string): string;const res = camelCase('hello world')qs.parse('?name=kkk&age=18')export { }
