ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

TypeScript 学习笔记(四)- extends 的作用

2022-02-22 15:35:05  阅读:189  来源: 互联网

标签:TypeScript string Dog 笔记 extends Animal 类型 type


一、继承

接口继承
  interface T1 {
    name: string
  }
  
  interface T2 {
    age: number
  }
  
  // 多重继承,逗号隔开
  interface T3 extends T1,T2 {
    gender: string
  }
 // T3 => { name: string; age: number, gender: string }
  
  const t3: T3 = {
    name: '111',
    gender: '1',
    age: 1
  }

T3除了自己的属性外,还同时拥有了来自T1和T2的属性

继承父类的方法和属性
class Animal {
  name = "animal";
  constructor(name: string) {
    this.name = name;
  }

  getName() {
    console.log(this.name);
  }
}

class Dog extends Animal {
  getAction() {
    console.log("run");
  }
}

const dog = new Dog("dog");
dog.getName(); // "dog"
dog.getAction();  // "run"

Dog 继承了父类的 getName 方法,可以在实例 dog 上直接调用。

二、条件判断

条件判断就是用来判断一个类型是不是可以分配给另一个类型,这在写高级类型的时候非常有用。

  type Animal = {
    name: string;
  }
  type Dog = {
    name: string;
  }
  type Bool = Dog extends Animal ? 'yes' : 'no'; //  'yes'
  type Bool = Animal extends Dog ? 'yes' : 'no'; //  'yes'

这是因为 Animal 和 Dog 的类型完全相同,或者说 Animal 类型的一切约束条件,Dog 都具备;换言之,类型为 Animal 的值可以分配给类型为 Dog 的值,反之亦然。

需要理解的是,这里A extends B,是指类型A可以分配给类型B,而不是说类型A是类型B的子集。

  type Animal = {
    name: string;
  }
  type Dog = {
    name: string;
    action: string;
  }
  type Bool = Animal extends Dog ? 'yes' : 'no'; //  'no'
  type Bool = Dog extends Animal ? 'yes' : 'no'; //  'yes'

当我们给Dog加上一个action属性,发现此时Bool是’no’,这是因为 Animal 没有类型为string的action属性,类型Animal不满足类型Dog的类型约束。

因此,A extends B,是指类型A可以分配给类型B,而不是说类型A是类型B的子集,理解extends在类型三元表达式里的用法非常重要。

再看一个例子

interface Animal {
  name: string;
}

interface Dog extends Animal {
  action: string;
}

  type Bool = Animal extends Dog ? 'yes' : 'no'; //  'no'
  type Bool = Dog extends Animal ? 'yes' : 'no'; //  'yes'

简单来说,如果extends前面的类型能够赋值给extends后面的类型,那么表达式判断为真,否则为假。

上面的示例中,Dog是Animal的子类,父类比子类的限制更少,能满足子类,则一定能满足父类,Dog类型的值可以赋值给Animal类型的值,判断为真。

三、泛型条件判断

  type A1 = 'x' extends 'x' ? string : number; // string
  type A2 = 'x' | 'y' extends 'x' ? string : number; // number
  
  type P<T> = T extends 'x' ? string : number;
  type A3 = P<'x' | 'y'> // string | number

A1和A2是extends条件判断的普通用法,和上面的判断方法一样。

P是带参数T的泛型类型,其表达式和A1,A2的形式完全相同,A3是泛型类型P传入参数’x’ | 'y’得到的类型,A3和A2的类型相似,但是结果不同,出现这个结果的原因是所谓的分配条件类型

对于使用extends关键字的条件类型(即上面的三元表达式类型),如果extends前面的参数是一个泛型类型,当传入该参数的是联合类型,则使用分配律计算最终的结果。分配律是指,将联合类型的联合项拆成单项,分别代入条件类型,然后将每个单项代入得到的结果再联合起来,得到最终的判断结果。

上面的例子可以拆分

type P<T> = T extends 'x' ? string : number;
type A3 = P<'x' | 'y'> // string | number
  
P<'x' | 'y'> => P<'x'> | P<'y'>
P<'x'> = 'x' extends 'x' ? string : number => string
P<'y'> = 'y' extends 'x' ? string : number => number
P<'x' | 'y'> = P<'x'> | P<'y'> = string | number

总之,满足两个要点即可适用分配律:

  1. 参数是泛型类型,
  2. 代入参数的是联合类型

在泛型的条件判断中还有些特殊的情况

特殊的never

// never是所有类型的子类型
  type A1 = never extends 'x' ? string : number; // string

  type P<T> = T extends 'x' ? string : number;
  type A2 = P<never> // never

never被认为是空的联合类型,也就是说,没有联合项的联合类型,所以还是满足上面的分配律,然而因为没有联合项可以分配,所以P的表达式其实根本就没有执行,所以A2的定义也就类似于永远没有返回的函数一样,是never类型的。

防止条件判断中的分配

  type P<T> = [T] extends ['x'] ? string : number;
  type A1 = P<'x' | 'y'> // number
  type A2 = P<never> // string

在条件判断类型的定义中,将泛型参数使用[]括起来,即可阻断条件判断类型的分配,此时,传入参数T的类型将被当做一个整体,不再分配

四、泛型约束

在书写泛型的时候,我们往往需要对类型参数作一定的限制。

interface Person {
  name: string;
  age: number;
  gender: string;
}

class Student {
  constructor(private info: Person) {}

  getInfo<T extends keyof Person>(key: T): Person[T] {
    return this.info[key];
  }
}

const student = new Student({
  name: 'uuuu',
  age: 20,
  gender: 'male'
})
const test = student.getInfo('name');
console.log(test) // "uuuu"

这里extends对传入的参数作了一个限制,参数必须是 Person的成员名的联合类型,避免传入其他key。

参考链接
Typescript extends使用
TS关键字extends用法总结

标签:TypeScript,string,Dog,笔记,extends,Animal,类型,type
来源: https://blog.csdn.net/kelly0721/article/details/122968285

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有