TypeScript 基础(记录学习)

Array 数组

在TypeScript中定义数组有两种方式web

// 第一种方式是能够在元素类型后面接上[]
const listOne: number[] = [1, 2, 3]  // 第二种方式是数组泛型,Array[元素类型] const listTwo: Array<number> = [4, 5, 6] 复制代码

Assertion 类型断言

类型断言分做两种形式typescript

// 第一种用 "尖括号"
const stringOne: any = 'hello TypeScript' const stringOneLength: number = (<string> stringOne).length   // 第二种用 关键字 “as” const stringTwo: any = 'hello TypeScript' const stringTwoLength: number = (stringTwo as string).length 复制代码

tips: 在TypeScript的JSX中类型断言可使用as,而不容许使用尖括号方式数组

Enum 枚举

使用枚举能够清晰地表达咱们的意图,好比 订单的状态开始是0,未结帐是1,运输中是2,运输完成是3,已收货是4编辑器

数字枚举

使用数字枚举来完成订单的状态函数

enum OrderStatus {
 START,  UNPAID,  SHIPPING,  SHIPPED,  COMPLETE }  console.log(  OrderStatus.START, // 0  OrderStatus.UNPAID, // 1  OrderStatus.SHIPPING, // 2  OrderStatus.SHIPPED, // 3  OrderStatus.COMPLETE, // 4 ) 复制代码

tips: 举可让咱们定义一些名字有意义的常量, 使用枚举能够清晰地表达咱们的意图ui

字符串枚举

enum OrderStatus {
 START = 'START',  UNPAID = 'UNPAID',  SHIPPING = 'SHIPPING',  SHIPPED = 'SHIPPED',  COMPLETE = 'COMPLETE' }  console.log(  OrderStatus.START, // START  OrderStatus.UNPAID, // UNPAID  OrderStatus.SHIPPING, // SHIPPING  OrderStatus.SHIPPED, // SHIPPED  OrderStatus.COMPLETE, // COMPLETE ) 复制代码

tips: 因为字符串枚举没有递增的含义,字符串枚举成员都必须手动初始化, 字符串枚举能进一步提高可读性,且在运行时中提供具备刻度性质的值es5

反向映射

enum Test {
 PRAISE }  console.log(  TEST.PRAISE, // 0  TEST[0] // 'PRAISE' )  // 缘由: 编译器拿到这段代码会编译到JavaScript,是以下这样的 (function (Enum) {  Enum[Enum['PRAISE'] = 0] = 'PRAISE' })(Enum || (Enum = {})) 复制代码

tips: 在字符串枚举中没有反向映射spa

Symbol

symbol成为一种新的原生类型,就像基本类型 numberstring 同样设计

const symbolOne = Symbol('hello')
const symboTwo = Symbol('hello')  symbolOne === symbolTwo // false 复制代码

tips: 经过一样的方式生成两个symbol,也是不一样的,由于symbol是惟一的code

Generic 泛型

泛型用于提高代码的重用性咱们但愿本身编写的代码,不管是模块仍是组件,不只能支持当前设计的数据类型,并且也能支持未来的数据类型。这在大型系统中是很是基础且重要的功能。因此咱们经常能在各类各样的静态类型语言中看到泛型设计,使得用户能够灵活地选择但愿支持的类型,而非局限于某一种类型

Fcuntion 泛型函数

function hello<T>(arg:T): T {
 return arg } console.log(  hello('string'),  hello(23),  hello({name: 'Praise'}) ) // string 23 { name: 'Praise' } 复制代码

tips: 泛型变量T,T表明用户即将传入的类型。类型既能够是number,也能够是string,而在最后,咱们还使用T做为返回值的类型。这就达到了返回 值和参数类型相同的目的,保持住了函数表达的准确性

使用泛型函数 有两种方法能够选择

// 第一种 使用熟悉的尖括号方式进行表达
const optput = hello<string>('hello TypeScript')  // 第二种 使用类型推断 const optput = hello('hello TypeScript') 复制代码

Variable 泛型变量

function hello<T>(arg: T): T {
 console.log(arg.length) // error TS2339: Property 'length' does not exist on type 'T'.  return arg } 复制代码

tips: 编译器会很是迅速地进行报错,告诉咱们泛型T并无length这个属性

可使用泛型数组来表达这样的状况

// 中括号 表达
function hello<T>(args: T[]): T[] {  console.log(args.length)  return args }  // Array 表达 function hello<T>(args: Array<T>): Array<T> {  console.log(args.length)  return args } 复制代码

Interface 高级类型

一个很经常使用的场景,好比函数传参

interface IPraise {
 name: string  age: number  hobby: Array<string> }  function person(arg: IPraise): IPraise {  return arg }  console.log(  person({name: 'Praise', age: 23, hobby: ['code']}) ) 复制代码

可选属性

将一个已知类型的每一个属性都变为可选的,好比像这样使用问号

interface IPraise {
 name?: string  age?: number  hobby?: Array<string> } 复制代码

tips: 在实例化IPraise时,咱们没必要给每一个属性都赋值

只读属性

interface IPraise {
 readonly name: string  readonly age: number  readonly hobby: Array<string> } 复制代码

索引签名

在不肯定属性数量的状况下可使用索引签名来添加一些额外的属性

interface IPraise {
 name: string  age: number  hobby: Array<string>  [propName: string]: any } 复制代码

tips: IPraise的属性值都是只读不可修改的

交叉类型与联合类型

type NewType = number & string
let newType: NewType  interface IPraiseOne {  name: string  age: number }  interface IPraiseTwo {  hobby: Array<string> }  type Praise = IPraiseOne | IPraiseTwo let praise: Praise 复制代码

映射类型

在映射类型里,新类型以相同的形式去转换旧类型里的每一个属性。例如,你能够令每一个属性成为只读类型或可选类型

type Readonly<T> = {
 readonly [P in keyof T]: T[p] }  type Partial<T> = {  [P in keyof T]?: T[P] }  type PersonPartial = Partial<Person> type ReadonlyPerson = Readonly<Person> 复制代码

tips: 内置的类型还有Required、Pick、Record、Exclude、Extract、NonNullable;读者能够本身尝试这些类型方法,它们的实现都在typescript/lib/lib.es5.d.ts中

// 一个Lodash中常见的pluck函数,就是从对象中选取属性的子集. 下面是pluck函数的简化版示例
function pluck(obj, names) {  return names.map(name => obj[name]) } 复制代码

若是须要在TypeScript中使用这个函数,要经过索引类型查询索引访问操做符:

function pluck<T, K extends keyof T>(obj: T, names: K[]): T[K][] {
 return names.map(name => obj[name]) }  interface Person {  name: string  age: number }  const person: Person = {  name: 'Praise',  age: 23 }  pluck(person, ['name']) // Praise 复制代码

tips: 编译器会检查传入的值是不是Person属性的一部分

让咱们解释一下上面代码的意义

  1. 泛型: 这里有T和K两种类型。根据类型推断,第一个参数obj就是person,类型会被推断为Person
  2. 类型推断: 第二个参数,咱们能够从右往左进行阅读。 keyof关键字能够获取T,也就是Person的全部属性名,即['name','age']
  3. 类型索引: extends关键字让泛型K继承了Person的全部属性名,即['name','age'],依托于 keyof关键字完成了类型索引
  4. 索引访问操做符: 返回值的类型是T[K][],阅读起来有点困难。它实际表述的意思是,变量T取属性K的值的数组,其中T[K]就是索引访问操做符