【typescript基础篇】(第七章) 剩余知识点

112 阅读5分钟

一些补充

unknown类型

  • unknown 类型代表任何值。这与 any 类型类似,但更安全,因为对未知 unknown 值做任何事情都是不合法的。
  • unknown 类型被称作安全的any

// unknown 类型代表任何值。这与 any 类型类似,但更安全,因为对未知 unknown 值做任何事情都是不合法的。
// unknown 类型被称作安全的any

// 1.任何类型都可以赋值给unknown类型
let str:unknown;
str = 18;
str = "张馨予";
str = false;

// 2.不能将unknown类型赋值给其它类型
let val:unknown = 18;
let num: number;
// num = val; // 报错
// 使用类型断言
num = val as number;
// 使用类型缩小
if(typeof val == "number") {
  num = val;
}

// 3.unknown与其它任何类型组成的交叉类型最后都是其它类型
type MyType1 = number & unknown;
type MyType2 = unknown & boolean;
let a:MyType1 = 18;
let b:MyType2 = true;


// 4.unknown除了与any以外, 与其它任何类型组成的联合类型最后都是unknown类型
type MyType3 = unknown | any;
type MyType4 = unknown | number;
type MyType5 = unknown | string | boolean;


// 5.never类型是unknown类型的子类型
type MyType6 = never extends unknown ? true : false;

map类型

Map 对象保存键值对,并且能够记住键的原始插入顺序。

任何值(对象或者原始值) 都可以作为一个键或一个值。

Map 是 ES6 中引入的一种新的数据结构

可以使用for of 进行迭代

创建map:

let myMap = new Map();

Map 相关的函数与属性:

  • map.clear() – 移除 Map 对象的所有键/值对 。
  • map.set() – 设置键值对,返回该 Map 对象。
  • map.get() – 返回键对应的值,如果不存在,则返回 undefined。
  • map.has() – 返回一个布尔值,用于判断 Map 中是否包含键对应的值。
  • map.delete() – 删除 Map 中的元素,删除成功返回 true,失败返回 false。
  • map.size – 返回 Map 对象键/值对的数量。
  • map.keys() - 返回一个 Iterator 对象, 包含了 Map 对象中每个元素的键 。
  • map.values() – 返回一个新的Iterator对象,包含了Map对象中每个元素的值 。
let nameSiteMapping = new Map();
 
// 设置 Map 对象
nameSiteMapping.set("邱淑贞", 1);
nameSiteMapping.set("宋茜", 2);
nameSiteMapping.set("景甜", 3);
 
// 获取键对应的值
console.log(nameSiteMapping.get("Runoob"));     // 2
 
// 判断 Map 中是否包含键对应的值
console.log(nameSiteMapping.has("Taobao"));       // true
console.log(nameSiteMapping.has("Zhihu"));        // false
 
// 返回 Map 对象键/值对的数量
console.log(nameSiteMapping.size);                // 3
 
// 删除 Runoob
console.log(nameSiteMapping.delete("Runoob"));    // true
console.log(nameSiteMapping);
// 移除 Map 对象的所有键/值对
nameSiteMapping.clear();             // 清除 Map
console.log(nameSiteMapping);

// 迭代 Map 中的 key
for (let key of nameSiteMapping.keys()) {
    console.log(key);
}
// 迭代 Map 中的 value
for (let value of nameSiteMapping.values()) {
    console.log(value);
}
// 迭代 Map 中的 key => value
for (let entry of nameSiteMapping.entries()) {
    console.log(entry[0], entry[1]);
}
// 使用对象解析
for (let [key, value] of nameSiteMapping) {
    console.log(key, value);
}

索引类型

  • 我们可以使用一个索引访问类型来查询另一个类型上的特定属性
  • 格式: [ key]
  • 注意点: 不会返回null/undefined/never类型

// 我们可以使用一个索引访问类型来查询另一个类型上的特定属性
// 格式: []

class Person {
  name: string 
  age: number
}

type MyIndex = Person["name"];
let a:MyIndex = "赵韩樱子";
console.log(a);

//  获取指定对象, 部分属性的值, 放到数组中返回
let obj = {
  name:'吴倩',
  age:18,
  gender: true
}
function getValues<T, K extends keyof T>(obj:T, keys:K[]):T[K][] {
  let arr = [] as T[K][];
  keys.forEach(key=>{
      arr.push(obj[key]);
  })
  return arr;
}
let res = getValues(obj, ['name', 'age']);
console.log(res);

// 不会返回null/undefined/never类型
interface TestInterface {
    a:string,
    b:number,
    c:boolean,
    d:symbol,
    e:null,
    f:undefined,
    g:never
}
type MyType = TestInterface[keyof TestInterface];

条件类型

  • 条件类型的形式看起来有点像JavaScript中的条件表达式:T extends U ? TrueType : FalseType
  • 应用场景: 解决函数重载问题

// 1.条件类型
// 条件类型的形式看起来有点像JavaScript中的条件表达式
// T extends U ? TrueType : FalseType

interface IName {
  name: string
}

interface IAge {
  age: number
}

// function reLoad(name: string): IName;
// function reLoad(age: number): IAge;
// function reLoad(nameOrAge: string | number): IName | IAge;
// function reLoad(nameOrAge: string | number): IName | IAge {
//   throw ""
// }

// 条件类型
type MyType<T> = T extends string ?: string : any
type res = MyType<string>


// 2.应用场景:解决函数重载问题
type Condition<T> = T extends string ? IName : IAge


function reLoad<T extends number | string>(idOrName: T): Condition<T> {
  throw ""
}

let res1 = reLoad("王丽坤") 
let res2 = reLoad(100) 

分布式条件类型

  • 当条件类型作用于一个通用类型时,当给定一个联合类型时,它们就变成了分布式的
  • 通常情况下,分布性是需要的行为。为了避免这种行为,你可以用方括号包围 extends 关键字的每一 边。

// 定义:被检测类型是一个联合类型的时候, 该条件类型就被称之为分布式条件类型

// type MyType<T> = T extends any ? T : never;
// type res = MyType<string | number | boolean>;


// 从T中剔除可以赋值给U的类型。 Exclude
// type res = Exclude<string | number | boolean, number>


// 提取T中可以赋值给U的类型。 Extract
// type res = Extract<string | number | boolean, number>

// 从T中剔除null和undefined。 NonNullable
// type res = NonNullable<string | boolean | null | undefined>

// 获取函数返回值类型。 ReturnType
// type res = ReturnType<()=>number>

// 获取一个类的构造函数参数组成的元组类型。 ConstructorParameters
// class Person {
//     constructor(name:string, age:number){}
// }
// type res = ConstructorParameters<typeof Person>;


// 获得函数的参数类型组成的元组类型。 Parameters
// function say(name:string, age:number, gender:boolean) {
// }
// type res = Parameters<typeof say>;

infer关键字推断

  • 条件类型为我们提供了一种方法来推断我们在真实分支中使用 infer 关键字进行对比的类型
  • 我们可以使用 infer 关键字编写一些有用的辅助类型别名

// 假如想获取数组里的元素类型,如果是数组则返回数组中元素的类型,否则返回这个类型本身
type Id = number[];
type IName = string[];

type Unpacked<T> = T extends IName ? string : T extends Id ? number : T;

type idType = Unpacked<Id>; // idType 类型为 number
type nameType = Unpacked<IName>; // nameType 类型为string


// 使用infer简化操作
type ElementOf<T> = T extends Array<infer E> ? E : T;
type res1 = ElementOf<string[]>; // string
type res2 = ElementOf<boolean>; // boolean


// infer可以推断出联合类型
type Foo<T> = T extends { a: infer U; b: infer U } ? U : never;
type T11 = Foo<{ a: string; b: number }>; // T11类型为 string | number