Typescript是JavaScript的超集;任何JavaScript环境都支持,最低可以编译到es3;被称为前端领域中的第二语言

1 开始

安装 yarn init 然后 yarn add typescript
安装完成后编译 yarn tsc tsname.ts
完成后生成一个同名的js文件
或者执行yarn tsc —init,会生成一个tsconfig.json文件,项目中执行yarn tsc,会按照配置编译整个项目

2 ts中的原始数据类型

  1. const a: string = 'jason';
  2. const b: number = 200;
  3. const c: boolean = true;
  4. const d: null = null;
  5. const e: void = undefined;
  6. const f: undefined = undefined;
  7. 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而接受原始类型则报错;

  1. const aa: object = function(){};
  2. const bb: object = [];
  3. const cc: object = {a: 1};
  4. // const dd: object = true; // 报错
  5. // 定义普通对象类型是要熟悉和值类型必须一致,不能少也不能更多 更专业的用interface
  6. const ee: {a: string, b: number } = {a: '1', b: 2}
  7. export {}

7 typescript中的数组类型

  1. // 数组类型
  2. const arr1: Array<number> = [1,2,3]
  3. const arr2: number[] = [1,2,3]
  4. //
  5. function sum(...args: number[]) {
  6. return args.reduce( (prev, current) => prev + current, 0)
  7. }
  8. sum(1,2,3,'ss') // ss会标记错误

8 typescript中的元组类型

  1. // 元组
  2. // 多或者少赋值都会报错
  3. const tuple: [string, number] = ['1',2]
  4. // 可以用数组下标获取
  5. const age = tuple[0]
  6. const name = tuple[1]
  7. // 也可用数组解构取值
  8. const [a,b] = tuple;
  9. // 一般用来返回函数固定格式值
  10. export {}

9 typescript中的枚举类型

  1. // 枚举类型
  2. // 指定值
  3. enum PostStatus {
  4. Draft = 0,
  5. Unpublished = 1,
  6. Published = 2
  7. }
  8. // 不指定值,默认从0开始累加
  9. enum PostStatus1 {
  10. Draft,
  11. Unpublished,
  12. Published
  13. }
  14. // 如果给第一个成员指定初始值,后续成员以此为基础累加
  15. enum PostStatus2 {
  16. Draft = 3,
  17. Unpublished,
  18. Published
  19. }
  20. // 字符串枚举则必须每个成员都设置初始值
  21. enum PostStatus3 {
  22. Draft = 'sss',
  23. Unpublished = 'sfsf',
  24. Published = 'sfs'
  25. }
  26. // 枚举类型编译后会入侵代码
  27. // PostStatus[0] => draft
  28. // 通过const添加的枚举值会在编译的时候移除枚举类型,并替换成对应的值
  29. const enum PostStatus4 {
  30. Draft = 'sss',
  31. Unpublished = 'sfsf',
  32. Published = 'sfs'
  33. }
  34. //使用枚举类型
  35. const post = {
  36. status: PostStatus4.Draft
  37. }
  38. export {}

10 typescript 中的函数类型

  1. // 函数类型
  2. // --------------函数声明
  3. // 默认值
  4. function fn1(a: string, b: string, c: number = 10) {
  5. return a + '-----' + b
  6. }
  7. // 可选参数
  8. function fn2(a: string, b: string, c?: number) {
  9. return a + '-----' + b
  10. }
  11. // 任意个数参数
  12. function fn3(a: string, b: string, ...rest: number[]) {
  13. return a + '-----' + b
  14. }
  15. // fn1(10,200) // 报错
  16. // fn1('ajson','tom','fsf')// 报错
  17. fn1('ajson','tom')
  18. // fn1(10,200) // 报错
  19. // fn1('ajson','tom','fsf')// 报错
  20. fn1('ajson','tom')
  21. // --------------函数表达式
  22. const fn4: (a: number, b: number) => string = function(a, b) {
  23. return `hello ${a}, hello ${b}`
  24. }
  25. export {}

11 typescript中的任意类型

  1. // any类型
  2. // 动态类型,可以接受任意类型参数
  3. function stringify(value: any) {
  4. return JSON.stringify(value);
  5. }
  6. stringify('string')
  7. stringify(200)
  8. stringify({a:1})
  9. // 重新赋值其他类型的值
  10. let foo: any = 'str';
  11. foo = 100;
  12. foo.fn();
  13. export {}

12 隐式类型推断

  1. // 隐式类型推断
  2. const age = 18;
  3. // age = 'sss';// 报错
  4. // ts无法推断类型时,会标记为any
  5. let fn; // let fn: any;
  6. export {}

13 断言

  1. // 类型断言
  2. export { }
  3. const arr = [20, 30, 40, 50];
  4. const num = arr.find(i => i>20);
  5. // const square = num * num; // 虽然已知类型了,但是ts会报错
  6. // 用断言来解决
  7. const num1 = num as number;
  8. const num2 = <number>num; // jsx中会与标签产生冲突
  9. // 断言不是转换,在编译环节发生

14 typescript接口interface

  1. // 接口
  2. interface Student {
  3. name: string
  4. age: number
  5. sex: string
  6. nation: string
  7. married?: boolean // 可选成员
  8. readonly level?: number // 只读成员
  9. }
  10. function getStudent(student: Student) {
  11. console.log(`${student.name}`)
  12. console.log(`${student.age}`)
  13. console.log(`${student.sex}`)
  14. console.log(`${student.nation}`)
  15. }
  16. //接口用来约束对象的结构,对象要实现接口就必须拥有接口的所有成员
  17. const info = {
  18. name: 'Jason',
  19. age: 18,
  20. sex: 'male',
  21. nation: 'hans',
  22. };
  23. // info.level = 10; // 报错
  24. getStudent(info)
  25. // 动态成员
  26. interface School {
  27. [prop: string]: string
  28. }
  29. const highSchool: School = {}
  30. highSchool.createDate = '1990-00-00';
  31. // highSchool.rebuildDate = 222;// 报错
  32. export {}

15 typescript中的类

es6以前都是用函数和原型来描述对象的特征属性,es6以后引入了class;

  1. // class
  2. class Person {
  3. public name: string; // public 默认是公有成员
  4. age: number = 18; // 构造函数赋值或者初始化赋值必须二选一
  5. private readonly score: number = 60; // 私有成员只能内部访问,readonly以后内部或者外部都不可修改
  6. protected site: string = 'r1l2' // 只能是内部或者子类访问
  7. constructor(name: string, age: number) {
  8. this.name = name;
  9. this.age = age;
  10. }
  11. sayHi(msg: string):void {
  12. console.log(`hello there, I am ${this.name}`)
  13. }
  14. }
  15. // 相比于js中的class,类的属性在使用之前必须先声明
  16. class Students extends Person {
  17. constructor(name: string, age: number){
  18. super(name, age);
  19. console.log(this.site) // protected属性可以在子类访问
  20. }
  21. }
  22. class NO1Students extends Person {
  23. // 通过private私有化构造函数,外部将无法通过此类进行实例化
  24. // 如果用protected修饰,则外部不可实例化,但是可继承
  25. private constructor(name: string, age: number){
  26. super(name, age);
  27. console.log(this.site) // protected属性可以在子类访问
  28. }
  29. // 此时只能通过静态方法来实例化,暴露给外部
  30. static getNo1(name: string, age: number) {
  31. return new NO1Students(name, age)
  32. }
  33. }
  34. const tom = new Person('Tom', 20);
  35. // console.log(tom.score) // 私有属性会报错
  36. const jason = NO1Students.getNo1('Jason', 18)

16 类和接口

  1. // 类和接口
  2. export { }
  3. // 多个类有共同点时用interface来抽象
  4. interface Animal {
  5. eat(food: string): void;
  6. sleep(where: string): void;
  7. }
  8. class Dog implements Animal {
  9. eat() {}
  10. sleep() {}
  11. }
  12. class Cat implements Animal {
  13. eat() {}
  14. sleep() {}
  15. }
  16. // 推荐更简单的接口减少耦合
  17. interface Eat{
  18. eat(food: string): void;
  19. }
  20. interface Sleep{
  21. sleep(food: string): void;
  22. }
  23. class pets implements Eat, Sleep {
  24. eat() {}
  25. sleep() {}
  26. }
  27. class person implements Eat, Sleep {
  28. eat() {}
  29. sleep() {}
  30. }

17 抽象类

抽象类有地类似接口,但是不同于接口,抽象类可以有一些具体的实现

  1. // 抽象类
  2. export { }
  3. abstract class Pets {
  4. eat(food: string): void {
  5. console.log(`I like to eat-----`)
  6. }
  7. abstract run(legs: number): void; // 抽象方法不需要方法体
  8. }
  9. // 抽象类只能被继承,不能用new关键词实例化
  10. class Dog extends Pets {
  11. // 必须实现抽象方法
  12. run(legs: number) {
  13. console.log(`I run by my ${legs} legs`)
  14. }
  15. }
  16. const dog = new Dog()
  17. dog.eat('火腿')
  18. dog.run(4)

18 泛型

  1. // 泛型
  2. function createNumberArray(length: number, value: number): number[] {
  3. const arr = new Array<number>(length).fill(value);
  4. return arr;
  5. }
  6. function createStringArray(length: number, value: string): string[] {
  7. const arr = new Array<string>(length).fill(value);
  8. return arr;
  9. }
  10. // 泛型参数 createArray<T>中的T
  11. function createArray<T>(length: number, value: T): T[] {
  12. const arr = new Array<T>(length).fill(value);
  13. return arr;
  14. }
  15. const createStr = createArray<string>(3, '20'); // [20,20,20]

19 类型声明

  1. // 类型声明
  2. // 引入外部的js时,如果没有类型声明文件就安装@types/类型 ,如果还没有就自己声明一个类型
  3. import { camelCase } from 'loadsh';
  4. import qs from 'query-string';
  5. // declare function camelCase(params:string): string;
  6. const res = camelCase('hello world')
  7. qs.parse('?name=kkk&age=18')
  8. export { }