ts 接口兼容性,跟ts类型没有关系,只跟属性有关系

  1. namespace a {
  2. //接口的兼容性
  3. interface Animal {
  4. name: string;
  5. age: number;
  6. }
  7. interface Person {
  8. name: string;
  9. age: number;
  10. speak: (words: string) => void
  11. }
  12. function getName(animal: Animal): string {
  13. return animal.name;
  14. }
  15. let p: Person = {
  16. name: 'aaa',
  17. age: 10,
  18. speak() { }
  19. }
  20. console.log(getName(p));
  21. //基本类型的兼容性
  22. //可以把一个具体的值赋值给另一个 更广泛的类型
  23. let num: string | number;
  24. let str: string = "string";
  25. num = str;
  26. let num2: {
  27. toString(): string
  28. }
  29. let str2: string = "asda";
  30. //这里只要赋值的变量有tostring方法就可以,也可以是另一个多有个值的对象,
  31. //只要有tostring方法就可以
  32. num = str2;
  33. }
  34. //类的兼容
  35. //跟 类型无关 ,跟属性有关,属性多于申明的 就可以值
  36. namespace b {
  37. class Animal {
  38. name: string
  39. }
  40. class Bird extends Animal {
  41. // swing: number
  42. }
  43. let a: Animal;
  44. a = new Bird();
  45. let b: Bird;
  46. b = new Animal();
  47. b = { name: 'asd' }; //不管这个对象的具体类型,只要属性有就可以
  48. }
  49. namespace c {
  50. //函数兼容性
  51. //函数兼容性比较参数
  52. //参数可以比之前少但是不能多
  53. //返回值可以比之前多,但是不能比之前少
  54. type sunFunction = (a: number, b: number) => number;
  55. let sum: sunFunction;
  56. function f1(a: number, b: number): number {
  57. return a;
  58. }
  59. sum = f1;
  60. function f2(a: number): number {
  61. return a;
  62. }
  63. sum = f2;
  64. function f3(): number {
  65. return 1;
  66. }
  67. sum = f3;
  68. function f4(a: number, b: number, c: number): number {
  69. return a;
  70. }
  71. // sum = f4;
  72. //返回值少了不可以,多了可以
  73. type GetPerson = () => { name: string, age: string };
  74. let getPerson: GetPerson;
  75. function g1() {
  76. return { name: '23', age: '12' };
  77. }
  78. getPerson = g1;
  79. function g2() {
  80. return { name: '23' };
  81. }
  82. // getPerson = g2; // 少了不行
  83. function g3() {
  84. return { name: '23', age: '12', data: '123' };
  85. }
  86. getPerson = g3; // 少了不行,多了可以
  87. }
  88. namespace d {
  89. //函数参数的协变
  90. //参数双向协定(但是现在实现不了了)
  91. //参数接受类型可以比之前多一些,但是不能比之前少,满足不了需求
  92. type logFunc = (a: number | string) => void;
  93. let log: logFunc;
  94. function log1(a: number | string | boolean) {
  95. console.log(a);
  96. }
  97. log = log1;
  98. //泛型的兼容性
  99. //判断兼容性的时候,先判断具体的类型,在进行兼容性判断
  100. //要看属性的兼容性,接口的值是空的时候是可以赋值的
  101. //但是如果 接口返回值不同时,就会报错
  102. interface Empty<T> {
  103. data: T
  104. }
  105. let x: Empty<string>; //{data:string}
  106. let y: Empty<number>; //{data:number}
  107. // x = y;
  108. //枚举的兼容性
  109. enum Colors {
  110. Red, Yellow
  111. }
  112. let c: Colors;
  113. c = Colors.Red;//0
  114. c = 1;
  115. let d: number;
  116. d = Colors.Yellow;//1
  117. }

类型保护

  1. namespace a {
  2. //类型保护 就是更精确的知道是哪种类型
  3. //ts会根据你的代码 查看你当前面的数据类型
  4. function double(input: string | number | boolean) {
  5. if (typeof input === 'string') {
  6. input.toLocaleLowerCase()
  7. } else if (typeof input === 'number') {
  8. input.toFixed();
  9. } else {
  10. input;
  11. }
  12. }
  13. class Animal {
  14. public name: string = 'asd';
  15. }
  16. class Birder extends Animal {
  17. public swing: string = "asd1";
  18. }
  19. function getName(a: Animal) {
  20. if (a instanceof Birder) {
  21. a.swing
  22. } else {
  23. a.name
  24. }
  25. }
  26. //null保护
  27. //如果在函数内部去兼容了null,有可能ts 因为作用域问题,识别不了
  28. //所以可以加一个非空断言
  29. function getFirstLetter(s: string | null) {
  30. // if (s === null) {
  31. // s = '';
  32. // }
  33. function ensure() {
  34. s = s || '';
  35. }
  36. ensure()
  37. // s = s || '';
  38. return s!.charAt(0);
  39. }
  40. //链判断运算符
  41. //1是先检查一种类型是不是存在,然后在访问该属性的运算符号,
  42. //2如果运算符左侧的操作数?.计算结果为undefind 或 null,则表达式
  43. //返回值为undefined ,否则正常触发目标的属性访问,方法或者函数调用
  44. let a1 = { b: 1, c: () => { } };
  45. let a2 = () => { };
  46. //先判断a是否为null或者undefind
  47. console.log(a1 ? a1.b : a1);
  48. a1?.['b'];
  49. a1?.c();
  50. a2?.();
  51. //可辨识的联合类型
  52. //1.就是利用联合 类型中的共有字段进行类型保护的一种技巧
  53. //2.相同字段的不同取值就是可辨识
  54. interface WarningButton {
  55. //接口class 的值是一个字符串,表示他也是一个类型
  56. //意思就是一个字面量 类型
  57. class: 'Warning',
  58. text1: '修改'
  59. }
  60. interface DangerButton {
  61. class: 'Danger',
  62. text2: '删除'
  63. }
  64. type Button = WarningButton | DangerButton;
  65. function getButton(button: Button) {
  66. if (button.class === "Warning") {
  67. button.text1;
  68. } else {
  69. button.text2;
  70. }
  71. }
  72. //判断是不是有哪些属性
  73. interface Bird {
  74. swing: number
  75. }
  76. interface Dog {
  77. leg: number
  78. }
  79. function getNumber(x: Bird | Dog) {
  80. //判断属性值是不是在x 内
  81. if ('swing' in x) {
  82. x.swing;
  83. } else {
  84. x.leg;
  85. }
  86. }
  87. }
  88. //自定义的类型保护
  89. //ts的类型保护实际就是一些表达式,会在运行时检查类型信息,以确保
  90. //在某个作用域里的类型时符合预期的
  91. //要自定义一个类型保护,只需要简单的为这个类型保护定义一个函数即可,
  92. //这个函数的返回值是一个类型谓词
  93. //类型谓词的语法就是: 当前函数某个参数参数 is Type
  94. namespace b {
  95. interface Bird {
  96. name1: '1'
  97. leg: number
  98. }
  99. interface Dog {
  100. name2: '2'
  101. leg: number
  102. }
  103. //自定义的类型保护器
  104. function isBird(x: Bird | Dog): x is Bird {
  105. //自定义一个规则
  106. return x.leg === 2;
  107. }
  108. function getAnimal(x: Bird | Dog) {
  109. if (isBird(x)) {
  110. x.leg; //x就是鸟
  111. x.name1
  112. } else {
  113. x.name2 //就不是鸟
  114. }
  115. }
  116. let x: Bird = { name1: '1', leg: 2 };
  117. getAnimal(x);
  118. }

问题

1.一个函数可以绑定多个泛型么?
function swap(a: T, b: U) {
}

2.接口数据类型定义为什么有时候是冒号,有时候是=>
//定义数据类型就是: ,但是定义函数=>表示函数 后跟返回值
interface Bird {
name: string;
fly(): void;
speak: (words: string) => void;
}

3.类型兼容
//就是值在日常编程中 重新赋值不报错,也就是类型自动可以转化