TypeScript高级类型(泛型、索引签名类型、映射类型、索引查询类型)

本文深入探讨了TypeScript中的高级类型概念,包括泛型的使用,如函数、接口和类的泛型应用,以及泛型约束和简化调用。此外,还讲解了索引签名类型,适用于不确定对象结构的情况。最后,介绍了映射类型,用于创建基于旧类型的新类型,提高代码复用性和开发效率。
摘要由CSDN通过智能技术生成

TypeScript高级类型

1、泛型 和 keyof

泛型是可以在保证类型安全(不丢失类型信息)前提下,让函数等与多种类型一起工作,从而实现复用,常用于:函数、接口、class 中。

泛型的基本使用

泛型我理解为:是一个动态的类型变量、通过泛型传递不同的类型、提高复用性

  //创建泛型函数
function ID<Type>(value:Type):Type{
  return value
}

//调用泛型函数
const num= ID<number>(12)//以number类型调用泛型函数
const str= ID<string>('233')//以string类型调用泛型函数

解释:
  1. 语法:在函数名称的后面添加 <>(尖括号),尖括号中指定具体的类型,比如,此处的 number。
  2. 当传入类型 number 后,这个类型就会被函数声明时指定的类型变量 Type 捕获到。
  3. 此时,Type 的类型就是 number,所以,函数 id 参数和返回值的类型也都是 number。 同样,如果传入类型 string,函数 id 参数和返回值的类型就都是 string。 这样,通过泛型就做到了让 id 函数与多种不同的类型一起工作,实现了复用的同时保证了类型安全。
  

泛型函数的简化调用

在调用泛型函数时,根据类型推断的机制、可以省略 <类型> 来简化泛型函数的调用。

  //创建泛型函数
  function ID<Type>(value:Type):Type{
    return value
  }

  let num1=ID(12)
  let str1=ID('24')

推荐:使用这种简化的方式调用泛型函数,使代码更短,更易于阅读。

泛型约束

 添加泛型约束收缩类型,两种方式:1 指定更加具体的类型 2 添加约束。
1.指定更加具体的类型
  function ID<Type>(value:Type[]):Type[]{
    value.length  
    return value
  }

  将类型修改为 Type[](Type 类型的数组),
  因为只要是数组就一定存在 length 属性,因此就可以访问了。
2.添加约束

通过 extends 关键字使用该接口,为泛型(类型变量)添加约束。

  interface ILength{ length:number}
  // Type类型需要满足ILength中的要求:传入的参数要有length属性
  function id<Type extends ILength >(value:Type):Type{
    return value
  }

  id({length:2,name:'李hs'})
  id(['1','2'])
  id('2')

  //错误
  //id(1)

  注意:传入的实参(比如,数组)只要有 length 属性即可,
  这也符合前面讲到的接口的类型兼容性。
  
3.添加约束使用keyof

泛型的类型变量可以有多个,并且类型变量之间还可以约束

keyof 关键字接收一个对象类型,生成其键名称(可能是字符串或数字)的联合类型。

比如,创建一个函数来获取对象中属性的值:


  //extends keyof 声明 key值必须是Type类型中有的属性
  function getProp<Type,key extends keyof Type>(obj:Type,key:key){
    return obj[key]
  }

  getProp({name:'李寒松',age:18},'age')
  getProp({name:'李寒松',age:18},'name')
  

  //错误演示
  //getProp({name:'李寒松',age:18},'name1')

  类型变量 Key 受 Type 约束、只能访问对象中存在的属性。
  

泛型接口

泛型接口:接口也可以配合泛型来使用,以增加其灵活性,增强其复用性。

    interface IdFunc<Type>{
      id:(value:number)=>Type
      ids:()=>Type[]
    }

    let obj:IdFunc<number>={
      id:(value)=>value,
      ids:()=>[1,3,5]
    }

    obj.id(22)

  1. 在接口名称的后面添加 <类型变量>,那么,这个接口就变成了泛型接口。
  2. 接口的类型变量,对接口中所有其他成员可见,也就是接口中所有成员都可以使用类型变量。
  3. 使用泛型接口时,需要显式指定具体的类型(比如,此处的 IdFunc<nunber>)。
  
泛型接口扩展
JS 中的数组在 TS 中就是一个泛型接口。
const strs=['a','b','c']
strs.forEach(item=>{})

const nums=[1,2,3]
nums.forEach(item=>{})

解释:当我们在使用数组时,TS 会根据数组的不同类型,来自动将类型变量设置为相应的类型。
技巧:可以通过 Ctrl + 鼠标左键(Mac:option + 鼠标左键)来查看具体的类型信息。

泛型类

类似于泛型接口,在 class 名称后面添加 <类型变量>,这个类就变成了泛型类。

创建泛型类
 //创建泛型类
class GenericNumber<NumType>{
  defaultValue:NumType
  add:(x:NumType,y:NumType)=>NumType
}
//明确指定<类型>
const myNum=new GenericNumber<number>()
myNum.defaultValue=1

泛型工具类型

泛型工具类型:TS 内置了一些常用的工具类型,来简化 TS 中的一些常见操作。
说明:它们都是基于泛型实现的(泛型适用于多种类型,更加通用),并且是内置的,可以直接使用。

1.工具类型 Partial

Partial 用来构造(创建)一个类型,将 Type 的所有属性设置为可选。


  interface Props{
    id:string
    children:number[]
  }

  //Partial<Props>对象中的参数是可选的
  type partialProps=Partial<Props>

  let p2:partialProps={id:'001'}

  解释:构造出来的新类型 PartialProps 结构和 Props 相同,但所有属性都变为可选的。
  
2.工具类型 Readonly

Readonly 用来构造一个类型,将 Type 的所有属性都设置为 readonly(只读)。

 interface Props{
  id:string
  children:number[]
}
type ReadonlyProps=Readonly<Props>

let p1:ReadonlyProps={
  id:'1',
  children:[1,3]
}
//p1.id='22'//无法分配到 "id" ,因为它是只读属性。

3.工具类型 Pick<Type,Keys>

Pick<Type, Keys> 从 Type 中选择一组属性来构造新类型。

  interface Props{
  id:string
  children:number[],
  title:string
}

//拷贝Props中的属性形成新的类型
//传入的属性必须是Props中有的属性
type PickProps=Pick<Props,'id'|'children'>

4.工具类型 Record<Keys,Type>

Record<Keys,Type> 构造一个对象类型,属性键为 Keys,属性类型为 Type。

type RecordObj=Record<'a'|'b'|'c',number[]>

let obj:RecordObj={
  a:[1,3,5],
  b:[2,4,6],
  c:[3,5,7]
}

1. Record 工具类型有两个类型变量:1 表示对象有哪些属性 2 表示对象属性的类型。
2. 要创建的属性的类型是相同的可以使用Record工具类

2、索引签名类型

绝大多数情况下,我们都可以在使用对象前就确定对象的结构,并为对象添加准确的类型。
使用场景:当无法确定对象中有哪些属性(或者说对象中可以出现任意多个属性),此时,就用到索引签名类型了。

对象

前置知识:JS 中对象({})的键是 string 类型的。

interface AnyObject{
    [key:string]:number
}

let obj:AnyObject={
    a:2,
    abc:1,
    abcd:1245
}

数组

数组的键(索引)是数值类型。

//数组
const arr=[1,3,5]
arr.forEach

interface myArr<Type>{
    [index:number]:Type
}

let arr1:myArr<number>=[1,2,4]
arr1[0]

3、映射类型

映射类型:基于旧类型创建新类型(对象类型),减少重复、提升开发效率。

根据联合类型创建新类型

//传统写法
type PropKeys='x'|'y'|'z'
type Type1={ x:number; y:number;z:number}

//映射类型
type type2={[key in PropKeys]:number}

注意:映射类型只能在类型别名中使用,不能在接口中使用。

根据对象类型创建新类型

type Proos={ a:number;b:string;c:boolean}
//拿到所有键
type Type={ [key in keyof Proos]:number}

Partial是基于映射实现的

泛型工具类型(比如,Partial)都是基于映射类型实现的。

interface Props{id:string,children:number[]}
type partialProps=Partial<Props>

// type Partial<T> = {
//   [P in keyof T]?: T[P];
// };

解释:
1. keyof T 即 keyof Props 表示获取 Props 的所有键,也就是:'a' | 'b' | 'c'2.[] 后面添加 ?(问号),表示将这些属性变为可选的,以此来实现 Partial 的功能。
3. 冒号后面的 T[P] 表示获取 T 中每个键对应的类型。比如,如果是 'a' 则类型是 number;如果是 'b' 则类型是 string。
4. 最终,新类型 PartialProps 和旧类型 Props 结构完全相同,只是让所有类型都变为可选了。
5. 

4、索引查询类型 T[P]

T[P] 语法, 在 TS 中叫做索引查询(访问)类型
作用:用来查询属性的类型。

索引类型基本使用

type Props={a:number;b:number;c:number}
type TypeA=Props['a']


//索引查询类型模拟Partial类型
type MyPartial<T>={ [P in keyof T]?:T[P]}

type PartialProps=MyPartial<Props>
type TypeB=PartialProps['a']

解释:Props['a'] 表示查询类型 Props 中属性 'a' 对应的类型 number。所以,TypeA 的类型为 number。
注意:[] 中的属性必须存在于被查询类型中,否则就会报错。
 

索引类型查询多个

type Props={ a:number;b:string;c:boolean}
//字面量联合类型获取a、b的类型
type TypeA=Props['a'|'b']     //string | number

//keyof获取Props中所有的类型 
type TypeB=Props[keyof Props]   //string | number | boolean

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值