资料链接

Union Type

说明

  1. type UnionType = number | string;
  2. let x: UnionType;
  3. x = 1;
  4. x = "1";
  5. // Literal Types
  6. let y: "abc";
  7. y = "abc";
  8. // 编译不通过 设置类型为一个值时只能使用这个值作为其内容
  9. // y = "bcd";
  10. // 例如:骰子的数值 可以利用union 取值的并
  11. let dicNum: 1 | 2 | 3 | 4 | 5 | 6;

类型判断

  1. // UnionType存在一个问题 就是对于输入是union的,函数需要根据输入类型判断处理 方式大体分为三种
  2. // 1. 普通类型判断
  3. function getValueType(value: string | number) {
  4. if (typeof value === "string") {
  5. return 0;
  6. }
  7. if (typeof value === "number") {
  8. return 1;
  9. }
  10. }
  11. // 2. 多态的类型判断
  12. class Animal {
  13. name: string;
  14. constructor(name: string) {
  15. this.name = name;
  16. }
  17. eat() {
  18. console.log(`${this.name} whu chi`);
  19. }
  20. }
  21. class Cat extends Animal {
  22. meow() {
  23. console.log(`${this.name} Meow`);
  24. }
  25. }
  26. class Dog extends Animal {
  27. bark() {
  28. console.log(`${this.name} Wang Wang`);
  29. }
  30. }
  31. // 使用instanceof判断类型
  32. function getAnimalSound(animal: Cat | Dog) {
  33. if (animal instanceof Cat) {
  34. animal.meow();
  35. }
  36. if (animal instanceof Dog) {
  37. animal.bark();
  38. }
  39. }
  40. // 3. interface判断
  41. type Square = { size: number };
  42. type Rectangle = { width: number; height: number };
  43. type Shape = Square | Rectangle;
  44. // 需要找到差异 然后进行判断类型
  45. // 另外可以增加属性type 或者使用从基类继承的方式
  46. function area(geometry: Shape) {
  47. if ("size" in geometry) {
  48. return geometry.size * geometry.size;
  49. }
  50. if ("width" in geometry) {
  51. return geometry.width * geometry.height;
  52. }
  53. }

intersection types

说明

  1. type User = {
  2. name?: string | null;
  3. email: number | string;
  4. };
  5. type Email = {
  6. name?: number | string;
  7. email: string;
  8. };
  9. type ContactDetails = User & Email;
  10. // 关于属性的复合 应该有一套特殊的复合关系生成 比如有交集且不为undefined和null 输出交集 否则输出never类型 标识不存在该类型
  11. let a: ContactDetails = { name: undefined, email: "aa" };
  12. a.name = "Sam";
  13. a.email = "111@qq.com";
  14. // console.log(a);
  15. // not-null assertion
  16. let t!: { x: number };
  17. function initializeT() {
  18. // 可以让null check无效 因为这个声明表示它是一个非null的 原理应该是主动躲避编译器的检查
  19. t.x = 123;
  20. // 也可以写作
  21. t!.x = 123;
  22. }
  23. // 会报错
  24. // initializeT();
  25. // console.log(t.x);

interface和type的区别

image.png

  1. type基本可以覆盖interface的一切功能,除了覆盖声明(上述的),以及interface的继承是extends符合其他的语言习惯
  2. type包含基本的类型 如string type可以union和intersection
  3. interface其实更倾向于C++的struct,或者是一个类的某种实现;而type倾向于反应某个属性的具体类型,它更倾向于这个属性属于某种基本类型,而不是一个结构类型(虽然是可以这样定义的)

    never类型的使用

    never 可以理解为 空 | 空 就是空,任何类型都可以extends never 但是never只能extends never

  1. type Square2 = { type: "square"; size: number };
  2. type Rectangle2 = { type: "rectangle"; width: number; height: number };
  3. type Radius2 = { type: "radius"; radius: number };
  4. type Shape2 = Square2 | Rectangle2;
  5. // | Radius2;
  6. // 检验是否完成所有的case
  7. function area2(geometry: Shape2) {
  8. if (geometry.type === "square") {
  9. return geometry.size ** 2;
  10. }
  11. if (geometry.type === "rectangle") {
  12. return geometry.width * geometry.height;
  13. }
  14. // 测试下增加一种类型Radius2
  15. const _ensureAllCaseAreHandled: never = geometry;
  16. return _ensureAllCaseAreHandled;
  17. }

assert functions

如果typescript开启nullCheck,使用这种声明,可以减少不必要的判断(仅仅为了说明类型的状态,让编译器进行自动推断),可以用这样的声明

  1. // assert functions
  2. type Person = {
  3. name: string;
  4. dateOfBirth?: Date;
  5. };
  6. // 如果不满足条件则报错
  7. // 可以减少额外判断
  8. function assert(condition: unknown, message: string): asserts condition {
  9. if (!condition) throw new Error(message);
  10. }
  11. function assertDate(value: unknown): asserts value is Date {
  12. if (value instanceof Date) {
  13. return;
  14. } else {
  15. throw new TypeError("value is not a Date");
  16. }
  17. }

泛型和复杂类型

关于extends的说明

  1. 如果extends前面的类型能够赋值给extends后面的类型,那么表达式判断为真,否则为假;
  2. 对于object(结构,更倾向于interface),如果有extends关系;对于普通类型有包含关系 ‘string’|’number’ extends ‘string’,对于泛型,可以理解为一种特别的object 其extends关系和其生成的对象类型有直接关系
  3. exclude extract lowerCase这些基本都是作用在object的key上面 配合key使用 ``typescript // generic constraints // 对于泛型的一些限制 type NameFields = { firstName: string; lastName: string }; // 需求 给定的类型包含名和姓 输出增加属性 fullName 其中fullName和姓名相关 function addFullName<T extends NameFields>(obj: T): T & { fullName: string } { return { ...obj, fullName:${obj.firstName} ${obj.lastName}`, }; } const john = addFullName({ email: “john@exaple.com”, firstName: “John”, lastName: “Doe”, }); // console.log(john);

// 学会使用 typeof type JohnFields = typeof john; const john2: JohnFields = { email: “john@exaple.com”, firstName: “John”, lastName: “Doe”, fullName: “”, };

// lookup types interface ComplexType { property1: boolean; property2: boolean; property3: { property1: boolean; property2: boolean; }; } // 可以使用接口里的属性作为类型输出 function getProperty3(): ComplexType[“property3”] { return { property1: true, property2: false, }; }

// keyof type type abc = keyof JohnFields; interface Student { name: string; age: number; grade: number; } const student: Student = { name: “sunwei”, age: 24, grade: 99, };

function propertyGet(obj: Obj, key: Key) { const value = obj[key]; return value; } const age = propertyGet(student, “age”);

function propertySet( obj: Obj, key: Key, // lookup value: Obj[Key] ) { obj[key] = value; } propertySet(student, “age”, 30); // propertySet(student, “class”, 30); // 可以识别对应类型的变更 // propertySet(student, “age”, “ab”);

// conditional type 条件类型 关于条件的三目运算 type IsNumber = T extends number ? “number” : “other”; type WithNumber = IsNumber; type WithOther = IsNumber;

export type TypeName = T extends string ? “string” : T extends number ? “number” : T extends boolean ? “boolean” : object; function typeName(t: T): TypeName { return typeof t as TypeName; } const str = typeName(“hello”); const num = typeName(123); const bool = typeName(true); const obj = typeName(null);

// infer type 类似于柯里化 然后代替被替换的元素 只能用于extends中 // 获取数组内的类型 type UnboxArray = T extends Array ? Member : T;

type UnboxedStringArray = UnboxArray; type UnboxedNumberArray = UnboxArray; type AnythingElse = UnboxArray;

// 获取函数的输出 type ReturnType = T extends (…args: any) => infer R ? R : never; type TestFunc = (x: number) => string; type RetType = ReturnType; type RetType2 = ReturnType;

const numFunc = (x: number) => x.toString(); type RetType3 = ReturnType;

// Map type interface Point { readonly x: number; y?: number; } // +-标识对特性的增加或删除 删除有的 没有的不删除 type Mapped = { -readonly [P in keyof T]+?: T[P]; }; type Result = Mapped;

// Partial // 让object的所有key变为可选 type Partial = { [P in keyof T]?: T[P]; }; type Result2 = Partial; // 让object的所有key变为只读 type Readonly = { readonly [P in keyof T]: T[P]; }; type Result3 = Readonly;

// Pick 选择部分属性 类似于filter

// type Pick = { // [P in keyof R]: T[R]; // }; interface IAbc { readonly a: number; b?: string; c: boolean; } type PickAb = Pick; let pickAbObject: PickAb = { a: 1, b: “test”, }; ```