类型思维

  • 思维方式决定了编程习惯
  • 编程习惯奠定了工程质量
  • 工程质量划定了能力边界

强类型与弱类型

对于强类型语言没有一个准确的定义,其中一种定义是:

在强类型语言中,当一个对象从调用函数传递到被调用函数时,其类型必须与被调用函数中上面的类型兼容

  1. A() {
  2. B(x)
  3. }
  4. B(y) {
  5. // y 可以被赋值x,程序运行良好
  6. }

后者对其的定义更加准确

强类型语言:不允许改变变量的数据类型,除非进行强制类型转换

什么是弱类型语言:

变量可以被赋值不同的数据类型

静态类型语言与动态类型语言

  • 静态类型语言:在编译阶段确定所有变量的类型
  • 动态类型语言:在执行阶段确定所有变量的类型 | 静态类型语言 | 动态类型语言 | | —- | —- | | 对类型极度严格 | 对类型非常宽松 | | 立即发现错误 | Bug可能隐藏数月甚至数年 | | 运行时性能好 | 运行时性能差 | | 自文档化 | 可读性差 |

动态类型语言的支持者认为:

  • 性能时可以改善的(V8引擎),而语言的灵活性更加重要
  • 隐藏的错误可以通过单元测试发现
  • 文档可以通过工具生成

image.png

第一个 TypeScript 程序

  1. interface Persen {
  2. name: string;
  3. age?: number;
  4. }
  5. let zhangsan: Persen = {
  6. name: 'zhangsna',
  7. }
  8. const add = (s: string, n: number): number => {
  9. return Number(s) + n;
  10. }
  11. class Animal {
  12. name: string
  13. constructor(name: string) {
  14. this.name = name
  15. }
  16. run() {
  17. return `${this.name} is running`
  18. }
  19. }
  20. class Dog extends Animal {
  21. bark() {
  22. return `${this.name} is braking`
  23. }
  24. }
  25. class Cat extends Animal {
  26. static categories = ['mammal']
  27. constructor(name: string) {
  28. super(name)
  29. console.log(this.name)
  30. }
  31. run() {
  32. return `Meow,${super.run()}`
  33. }
  34. }
  35. // const dog = new Dog('xiaoming');
  36. // console.log(dog.run());
  37. // console.log(dog.bark());
  38. const mao = new Cat('mao')
  39. console.log(mao.run())
  40. console.log(Cat.categories)
  41. interface Radio {
  42. switchRadio(trigger: boolean): void
  43. }
  44. interface Battery {
  45. checkBatteryStatus(): void
  46. }
  47. interface RadioWithBattery extends Radio {
  48. checkBatteryStatus(): void
  49. }
  50. class Car implements Radio {
  51. switchRadio(trigger: boolean): void {
  52. }
  53. }
  54. class Cellphone implements RadioWithBattery {
  55. switchRadio(trigger: boolean): void {
  56. }
  57. checkBatteryStatus(): void {
  58. }
  59. }
  60. enum Diretion {
  61. Up = 10,
  62. Down,
  63. Left,
  64. Right
  65. }
  66. console.log(Diretion.Up)
  67. console.log(Diretion[0])
  68. interface IWithLength {
  69. length: number
  70. }
  71. function echo<T extends IWithLength>(arg: T): T {
  72. console.log(arg.length)
  73. return arg
  74. }
  75. const result = echo('str')
  76. interface IName {
  77. name: string
  78. }
  79. type IPerson = IName & { age: number }
  80. let person: IPerson = { name: '123', age: 12 }

接口

接口命名时通常用Ixx,如 interface IName

函数

继承和成员修饰符

抽象类与多态

类与接口的关系

泛型

泛型函数与泛型接口

泛型类与泛型约束

类型检查机制

类型判断

类型兼容

结构之间兼容:成员少的兼容成员多的
函数之间兼容:参数多的兼容成员少的

接口类型兼容

函数类型兼容

  • 固定参数不兼容固定参数和剩余参数
  • 可选参数不兼容固定参数和剩余参数
  • 返回值类型一致或者兼容类型

    1. let a = (p1: number, p2: number) => {};
    2. let b = (p1?: number, p2?: number) => {};
    3. let c = (...arg: number[]) => {};
    4. a = b;
    5. a = c;
    6. b = c; //error
    7. b = a; //error

    枚举类型兼容

  • 枚举类型与数值类型是完全兼容的

  • 枚举类型之间完全不兼容

    类兼容性

    具有相同的实例成员,静态成员和构造函数不参与兼容性比较

    泛型兼容性

    只有泛型接口中类型T使用的时才会影响类型的兼容性

    类型保护

    typescript能够在特定的区块中保证变量属于某种确定的类型。可以在此区块中放心引用此类型的属性,或者调用此类型的方法。

  1. // instanceof
  2. if(lang instanceof Java) {
  3. lang.helloJava()
  4. } else {
  5. lang.helloJavaScript()
  6. }
  7. // in
  8. if('java' in lang) {
  9. lang.helloJava()
  10. } else {
  11. lang.helloJavaScript()
  12. }
  13. // typeof 判断基本类型
  14. if(typeof x === 'string') {
  15. x.length
  16. } else {
  17. x.toFixed(2)
  18. }
  19. // 类型保护函数
  20. function isJava(lang:Java | JavaScript): lang is Java {
  21. return (lang as Java).helloJava !== undefined
  22. }
  23. function getLanguage(type:Type,x:string|number) {
  24. let lang =type=Type.String?new Java():new JavaScript()
  25. if(isJava(lang)) {
  26. lang.helloJava()
  27. } else {
  28. lang.helloJavaScript()
  29. }
  30. }

高级类型

交叉类型与联合类型

索引类型

  1. # key 的类型是obj对象属性的联合类型
  2. let key: keyof obj;

注意点

一般情况下优先使用类型注解的方式,必须谨慎使用类型断言,如果你没有添加对应的属性ts不会发出警告

  1. interface Foo {
  2. bar: number;
  3. bas: string;
  4. }
  5. const foo = {} as Foo;

当 S 类型是 T 类型的子集,或者 T 类型是 S 类型的子集时,S 能被成功断言成 T。这是为了在进行类型断言时提供额外的安全性,完全毫无根据的断言是危险的,如果你想这么做,你可以使用 any。

参考

【1】TypeScript开发实战[视频]