TypeScript-类、继承、接口、泛型、tsconfig

/

一、类

何为类?简而言之就是程序之中所有的操作都需要通过对象来完成。

  1. class Person {
  2. // 在属性前使用 static 关键字,可以定义静态属性(类属性),不需要创建对象就可以使用 实例对象没有静态属性
  3. static age: number = 18;
  4. // 实例属性 readonly表示只读属性,不能修改
  5. // readonly name: string = "孙悟空";
  6. name = "孙悟空";
  7. // 定义方法 加上static 变成静态方法
  8. sayHello() {
  9. console.log("大家好");
  10. }
  11. }
  12. const per = new Person();
  13. console.log("per: ", per);
  14. console.log(Person.age);
  15. // console.log(per.age); 实例对象没有静态属性
  16. console.log(per.name);
  17. // per.name = "齐天大圣";
  18. console.log(per.name);
  19. // 方法
  20. per.sayHello();
  21. // Person.sayHello();

1.1 构造函数

在实例化一个类的时候,会自动调用该方法。

  1. class Dog {
  2. name: string;
  3. age: number;
  4. constructor(name: string, age: number) {
  5. this.name = name;
  6. this.age = age;
  7. }
  8. bark() {
  9. console.log("汪汪汪");
  10. }
  11. }
  12. const dog1 = new Dog("阿喵", 9);
  13. const dog2 = new Dog("阿呆", 6);
  14. console.log(dog1);
  15. console.log(dog2);

1.2 继承

作用是:共享父类的属性和方法

  1. (function () {
  2. // 定义公共类
  3. class Animal {
  4. name: string;
  5. age: number;
  6. constructor(name: string, age: number) {
  7. this.name = name;
  8. this.age = age;
  9. }
  10. sayHello() {
  11. console.log("动物在叫");
  12. }
  13. }
  14. // 使用继承后,子类中将拥有父类的所有属性和方法
  15. class Dog extends Animal {
  16. run() {
  17. console.log(`${this.name}在跑~~~`);
  18. }
  19. // 子类覆盖父类的方法 => 重写父类方法
  20. sayHello() {
  21. console.log("汪汪汪");
  22. }
  23. }
  24. class Cat extends Animal {
  25. sayHello() {
  26. console.log("喵喵喵");
  27. }
  28. }
  29. const dog = new Dog("阿呆", 8);
  30. const cat = new Cat("阿喵", 3);
  31. console.log("cat: ", cat);
  32. cat.sayHello();
  33. console.log("dog: ", dog);
  34. dog.sayHello();
  35. dog.run();
  36. })();

1.3 super 关键字

可通过super关键字调用父类的方法。

  1. // super 表示当前类的父类
  2. (function () {
  3. class Animal {
  4. name: string;
  5. constructor(name: string) {
  6. this.name = name;
  7. }
  8. sayHello() {
  9. console.log("大家好");
  10. }
  11. }
  12. class Dog extends Animal {
  13. age: number;
  14. constructor(name: string, age: number) {
  15. // 如果在子类中写了构造函数,相当于重写了父类的构造函数,此时需要对父类的构造函数进行调用
  16. super(name); // 相应的参数也要传入进去
  17. this.age = age;
  18. }
  19. sayHello() {
  20. // super 表示当前类的父类
  21. super.sayHello();
  22. }
  23. }
  24. const dog = new Dog("旺财", 3);
  25. dog.sayHello();
  26. })();

1.4 抽象类与抽象方法

  • 抽象类:即一种专门被其他类继承的类,生下来就是用来给别人继承的(即抽象类是父类),而且在抽象类当中可以添加抽象方法
  • 抽象方法:没有方法体的方法,子类必须实现父类的抽象方法
  1. (function () {
  2. /**
  3. * 以 abstract 开头的是抽象类,和其他类区别是:
  4. * 1.不能被创建实例
  5. * 2.抽象类可以添加抽象方法
  6. */
  7. abstract class Animal {
  8. name: string;
  9. constructor(name: string) {
  10. this.name = name;
  11. }
  12. /**
  13. * abstract 定义一个抽象方法
  14. * 1.没有方法体
  15. * 2.抽象方法只能定义在抽象类中
  16. * 3.子类必须对抽象方法进行重写
  17. */
  18. abstract sayHello(): void;
  19. }
  20. class Dog extends Animal {
  21. sayHello() {
  22. // super 表示当前类的父类
  23. console.log("汪汪汪~");
  24. }
  25. }
  26. // 非抽象类“Cat”不会实现继承自“Animal”类的抽象成员“sayHello”。
  27. class Cat extends Animal {
  28. sayHello() {
  29. console.log("喵喵喵~");
  30. }
  31. }
  32. const dog = new Dog("旺财");
  33. const cat = new Cat("阿喵");
  34. dog.sayHello();
  35. // const an = new Animal() // 报错:无法创建抽象类的实例。
  36. })();

二、接口

接口就是一组规范

接口与抽象类的区别:

  • 接口:
    1. 都是抽象方法
    2. 属性不能有值,只定义属性类型
    3. interface定义 implements 实现接口
  • 抽象类:
    1. 可以有抽象方法,也可以有普通方法
    2. class定义 extends 实现继承
  1. (function () {
  2. // type 描述一个对象的类型
  3. type myType = {
  4. name: string;
  5. age: number;
  6. };
  7. /* 类型声明不可重复声明 */
  8. // type myType = {
  9. // name: string;
  10. // age: number;
  11. // };
  12. /**
  13. * 接口:用来定义一个类的结构
  14. * 1.用来定义一个类中,应该包含那些属性和方法
  15. * 2.同时也可以当成类型声明去使用
  16. */
  17. interface myInterface {
  18. name: string;
  19. age: number;
  20. }
  21. /* 接口可以重复声明 */
  22. interface myInterface {
  23. gender: string;
  24. }
  25. const obj: myInterface = {
  26. name: "sss",
  27. age: 111,
  28. gender: "男",
  29. };
  30. /**
  31. * 接口可以在定义类的时候去限制类的值
  32. * 1.接口中的所有属性都不能有实际的值 属性不能有值,方法不能有方法体
  33. * 2.接口只定义对象的结构,而不考虑实际的值。
  34. * 3.接口中所有的方法都是抽象方法
  35. */
  36. interface myInter {
  37. name: string;
  38. sayHello(): void;
  39. }
  40. // 实现接口 => 使类满足接口的要求
  41. class MyClass implements myInter {
  42. name: string;
  43. constructor(name: string) {
  44. this.name = name;
  45. }
  46. sayHello(): void {
  47. console.log("大家好");
  48. }
  49. }
  50. })();

三、get set 及 public protected private

3.1 get And set

如需使用 getter、setter,TS中已帮我们内置了关键字 get、set 可直接跟上属性名,即可像正常对象的属性一样读取或设置该属性值。

  1. (function () {
  2. class Person {
  3. // TS可以在属性前添加修饰符
  4. /**
  5. * public 公共属性,可以在任意位置访问或修改 默认值,包括子类和实例
  6. * protected 受保护的属性,只能在当前类和当前类的子类中使用,不能在实例上访问
  7. * private 私有属性,只能在类内部访问或修改,不能在子类中访问
  8. */
  9. private _name: string;
  10. private _age: number;
  11. constructor(name: string, age: number) {
  12. this._name = name;
  13. this._age = age;
  14. }
  15. // 普通做法
  16. // getName() {
  17. // return this.name;
  18. // }
  19. // setName(value: string) {
  20. // this.name = value;
  21. // }
  22. // getAge() {
  23. // return this.age;
  24. // }
  25. // setAge(value: number) {
  26. // if (value >= 0) {
  27. // this.age = value;
  28. // } else {
  29. // throw new Error("年龄必须大于等于0");
  30. // }
  31. // }
  32. // TS中做法
  33. get name(): string {
  34. return this._name;
  35. }
  36. set name(value: string) {
  37. this._name = value;
  38. }
  39. get age(): number {
  40. return this._age;
  41. }
  42. set age(value: number) {
  43. if (value >= 0) {
  44. this._age = value;
  45. } else {
  46. throw new Error("年龄必须大于等于0");
  47. }
  48. }
  49. }
  50. const person = new Person("孙悟空", 18);
  51. // 普通做法
  52. // console.log(person.getName());
  53. // person.setName("猪八戒");
  54. // console.log(person.getName());
  55. // person.setAge(-5);
  56. // console.log(person);
  57. // TS做法
  58. console.log(person.name);
  59. person.name = "猪八戒";
  60. console.log(person.name);
  61. // person.age = -5;
  62. console.log(person.age);
  63. })();

3.2 public protected private

  1. class A {
  2. public name: string;
  3. protected age: number;
  4. private num: number;
  5. constructor(name: string, num: number, age: number) {
  6. this.name = name;
  7. this.age = age;
  8. this.num = num;
  9. }
  10. }
  11. class B extends A {
  12. test() {
  13. console.log(this.name);
  14. console.log(this.age);
  15. // console.log(this.num); // 属性“num”为私有属性,只能在类“A”中访问
  16. }
  17. }
  18. const b = new B("阿喵", 1, 3);
  19. console.log(b.name);
  20. // console.log(b.age); // 属性“age”受保护,只能在类“A”及其子类中访问。
  21. // console.log(b.num); // 属性“num”为私有属性,只能在类“A”中访问。
  22. /**
  23. * 语法糖,简写了属性的定义及赋值
  24. */
  25. class C {
  26. // 可以直接将属性定义在构造函数中
  27. constructor(public name: string, protected age: number) {}
  28. }
  29. const c = new C("阿呆", 8);
  30. console.log(c);

四、泛型

在定义函数或者类时,如果遇到类型不明确的,就可以使用泛型。
泛型就是一个不确定的类型。
在我们类型不明确的时候,整一个变量,用这个变量来表示类型(泛型)

  1. /**
  2. * 在定义函数或者类时,如果遇到类型不明确的,就可以使用泛型
  3. * => 泛型就是一个不确定的类型。
  4. * 泛型的作用就是,在我们类型不明确的时候,整一个变量,用这个变量来表示类型(泛型)
  5. */
  6. // 这个T是什么类型呢?谁都不知道,只有在函数执行的时候才能确定
  7. // 能体现出传入的参数类型,与返回的参数类型是同一类型
  8. function fn<T>(a: T): T {
  9. return a;
  10. }
  11. // 直接调用具有泛型的函数
  12. let result = fn(2); // TS会自动推断出参数类型
  13. let result2 = fn<string>("hello"); // 手动指定
  14. console.log("result: ", result);
  15. console.log("result2: ", result2);
  16. function fn2<T, K>(a: T, b: K): T {
  17. console.log(b);
  18. return a;
  19. }
  20. fn2<number, string>(123, "hello");
  21. interface Inter {
  22. length: number;
  23. }
  24. // T extends Inter 表示泛型T必须实现Inter接口,即必须是Inter实现类(子类)
  25. function fn3<T extends Inter>(a: T): number {
  26. return a.length;
  27. }
  28. fn3("123");
  29. // fn3(456); // 类型“number”的参数不能赋给类型“Inter”的参数。
  30. fn3({ name: "good", length: 5 });
  31. fn3([1, 2, 3, 4, 5, 6, 7, 8, 9]);
  32. class MyClass<T> {
  33. name: T;
  34. constructor(name: T) {
  35. this.name = name;
  36. }
  37. }
  38. const mc = new MyClass<string>("孙悟空");

五、tsconfig.js 配置文件解析

  1. {
  2. // include 包含
  3. // 一个(*)任意文件,两个(*)任意目录
  4. "include": ["./src/**/*"],
  5. // exclude 不包含 默认值:["node_modules","bower_components","jspm_packages"]
  6. // "exclude": ["./src/hello/**/*"],
  7. // 定义被继承的配置文件
  8. // "extends": "",
  9. // compilerOptions 编译选项
  10. "compilerOptions": {
  11. // 打包代码生成的格式
  12. // 'es3', 'es5', 'es6', 'es2015', 'es2016', 'es2017', 'es2018', 'es2019', 'es2020', 'es2021', 'esnext'
  13. "target": "ES3",
  14. // 支持的模块化格式 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015', 'es2020', 'esnext'.
  15. "module": "system",
  16. // 用来指定项目中要使用的库,为空的话则没有document这些代码提示,以此区分代码提示是在浏览器环境还是Node
  17. // 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'es2019', 'es2020', 'es2021', 'esnext', 'dom', 'dom.iterable', 'webworker', 'webworker.importscripts', 'webworker.iterable', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'es2018.asyncgenerator', 'es2018.asynciterable', 'es2018.intl', 'es2018.promise', 'es2018.regexp', 'es2019.array', 'es2019.object', 'es2019.string', 'es2019.symbol', 'es2020.bigint', 'es2020.promise', 'es2020.sharedmemory', 'es2020.string', 'es2020.symbol.wellknown', 'es2020.intl', 'es2021.promise', 'es2021.string', 'es2021.weakref', 'esnext.array', 'esnext.symbol', 'esnext.asynciterable', 'esnext.intl', 'esnext.bigint', 'esnext.string', 'esnext.promise', 'esnext.weakref'.
  18. // "lib": ['a'],
  19. // 指定输出文件目录
  20. "outDir": "./dist",
  21. // 全局作用域中的代码会合并到同一个文件中
  22. "outFile": "./dist/main.js",
  23. // 是否对 JS 文件进行编译:default:false
  24. "allowJs": true,
  25. // 检查 JS 代码是否符合 TS语法规范。检查强类型
  26. "checkJs": true,
  27. // 是否移除注释
  28. "removeComments": true,
  29. // 不生成编译后的文件 default:false
  30. "noEmit": false,
  31. // 有错误不生成编译文件 default:false
  32. "noEmitOnError": true,
  33. // strict 所有严格检查的总开关 default:false
  34. "strict": true,
  35. // 编译后的文件是否使用严格模式。 default:false
  36. "alwaysStrict": true,
  37. // 不允许隐式 any 类型 default:false(即默认可以使用 隐式 any)
  38. "noImplicitAny": false,
  39. // 不允许不明确类型的 this
  40. "noImplicitThis": false,
  41. // 严格的检查空值
  42. "strictNullChecks": true,
  43. }
  44. }

转载请注明作者和出处,并添加本页链接。
原文链接: //www.v2ci.com/32.html