0
点赞
收藏
分享

微信扫一扫

微软Windows生态是怎么打造成功的?

witmy 2024-02-11 阅读 8

TypeScript笔记

1. 基本类型

JS内置类型、全局作用域 global 上存在的对象(Window内属性对象):Array、Date、Error 等、HTMLElement、NodeList、MouseEvent 等。

2. 数组、元祖、函数类型

3. class、interface、implements

4. interface与数组与鸭子类型(duck typing)

5. interface与type

有相似功能却不同的两种定义数据类型的方式。

  • 相同点
    1. 都可以定义一个对象或函数
    2. 都允许继承。interface 使用 extends 实现继承, type 使用交叉类型实现继承。
      • interface通过extends可以继承interface / type
      • type通过&继承属性,可以继承interface / type定义的类型。
    // 这两种写法都可以定义函数类型
    type addType = (num1:number,num2:number) => number
    
    interface addType {
        (num1:number,num2:number):number
    }
    
  • 不同点
    1. interface(接口) 是 TS 设计出来用于【定义对象类型】的,可以对对象的形状进行描述。
    2. type 是类型别名,用于给各种类型定义别名,让 TS 写起来更简洁、清晰。
    3. type 可以声明基本类型、联合类型、交叉类型、元组,interface 不行
    4. interface可以合并重复声明,type 不行。
    interface Person {
      name: string
    }
    
    interface Person {         // 重复声明 interface,就合并了
      age: number
    }
    
    const person: Person = {
      name: 'lin',
      age: 18
    }
    

6. 泛型

举例使用泛型:在不知道可能会传入什么类型的变量前提下,为了约束函数中进、出是同一种而采用的类型占位符。

// type / interface、函数都可以使用泛型
// type Print = <T>(arg: T) => T
interface Print<T> {
  (arg:T):T
}
interface Print1<T,U> {
  (arg:T):T
  name:U
}

const printFn:Print<string> = function Print(arg) {
  console.log(arg)
  return arg
}
function test<T>(param:T):T{
  return param;
}
const str:string = test<string>('12121')

// class / 数组定义等也可以使用泛型
class Test<T>{
  print(arg:T):T|undefined{
    return arg;
  }
}
const str = new Test<string>()

const arr:Array<number> = [1,2,3] // const arr: number[] = [1,2,3]

搞懂了什么是泛型之后,现在我们可以尝试使用和约束泛型。精确约束内部属性主要可以使用extends。笔记中我分为属性约束和副作用(内部函数)约束

// 属性约束
function printLength<T>(arg: T): T {
  console.log(arg.length)
  return arg
}
// 报错,因为不确定arg上是否有length属性,这时就可以使用interface / extends去约束
interface ILength {
  length: number
}

function printLength<T extends ILength>(arg: T): T {
    console.log(arg.length)
    return arg
}

// 副作用约束
// 一个公共方法(不确定传入值),内部异步调用(不确定回传),如下,默认的res返回是any,无法得到类型约束
function request(url:string) {
  return fetch(url).then(res => res.json())
}
// 为了更好地约束res回传值,我们可以使用泛型
interface UserInfo {
  name: string
  age: number
}

function request<T>(url:string): Promise<T> {
    return fetch(url).then(res => res.json())
}
 
request<UserInfo>('user/info').then(res =>{
    console.log(res)
})

索引类型 —— 我的理解中,索引类型是用于进一步简化复杂的约束操作而定义的几个方法,其中的约束仍然是针对于属性约束。
主要可以实现实现动态属性的检查 keyof(索引查询)、T[K](索引访问) 和 extends (泛型约束)。

// keyof(索引查询) 可以用于获取某种类型的所有键,其返回类型是联合类型。
interface IPerson {
  name: string;
  age: number;
}
type Test = keyof IPerson; // 'name' | 'age'

// T[K](索引访问) 表示接口 T 的属性 K 所代表的类型,
interface IPerson {
  name: string;
  age: number;
}
let type1:  IPerson['name'] // string

// T extends U,表示泛型变量可以通过继承某个类型 同上文

泛型约束使用题目: 下方的变量中使用原本没有的属性却没有提示,该如何纠正?

const userInfo = {
  name: 'lin',
  age: '18',
}

function getValues(userInfo: any, keys: string[]) {
  return keys.map(key => userInfo[key])
}

// 抽取指定属性的值
console.log(getValues(userInfo, ['name','age']))  // ['lin', '18']
// 抽取obj中没有的属性:(并没有报错)
console.log(getValues(userInfo, ['sex','outlook']))  // [undefined, undefined]

// 原本定义了一个interface userInfo,但是公用函数中最好都使用泛型占位、让函数实例填充,而不是指定具体类型
function getValues<T,K extends keyof T>(userInfo: T, keys: K[]) {
  return keys.map(key => userInfo[key])
}

console.log(getValues(userInfo, ['name','age']))  
console.log(getValues(userInfo, ['sex','outlook'])) 

7、其他简便运算符号:in、Pick、Partial、Exclude、Omit、Extract等

// in 用于遍历联合类型
type Person = "name" | "school" | "major"
type Obj =  {
  [p in Person]: string
}

// Partial 将类型映射成可选属性
interface IPerson {
  name: string
  age: number
}
type IPartial = Partial<IPerson>
let p1: IPartial = {}

8. TypeScript声明文件d.ts

如果项目是js写的,后面需要接进ts项目,那需要写一个.d.ts的声明文件来告诉外部的ts检测 我这个是什么类型,我这里已经定义了,不需要您的类型检查了。如果是ts项目那就不需要额外书写声明文件。 大部分项目的声明都放在@types/xx 这个依赖中,直接npm到项目就可以了。
declare class Test {}
以上是将HTML代码转换为Markdown格式的文本。

举报

相关推荐

0 条评论