• home > webfront > ECMAS > typescript >

    TS数据类型(1):从Utility Types发微,分类学习笔记

    Author:zhoulujun Date:

    TS类型杂记:集合类:Partial Required, Pick Omit;联合类型操作:Exclude Extract、NonNullable;函数类:InstanceType、ReturnType、ThisType、Parameters、ConstructorParameters;类型模式匹配技术

    TS在全局内置了很多Utility Types,可以极大的提高我们开发效率。

    具体参看:https://www.typescriptlang.org/docs/handbook/utility-types.html#handbook-content




    集合类:Partial/Required, Pick/Omit

    Partial<Type>

    作用:它会将Type内所有属性置为可选,返回一个给定类型Type的子集

    interface Todo {
      title: string;
      description: string;
    }
    
    // 场景:只想更新toTo部分属性,Partial的使用就比较优雅了
    function updateTodo(todo: Todo, fieldsToUpdate: Partial<Todo>) {
      return { ...todo, ...fieldsToUpdate };
    }
     
    const todo1 = {
      title: "organize desk",
      description: "clear clutter",
    };
     
    const todo2 = updateTodo(todo1, {
      description: "throw out trash",
    });

    与Partial相反的是Required

    Required<Type>

    作用:构建返回一个Type的所有属性为必选的新类型

    interface Props {
      a?: number;
      b?: string;
    }
    const obj: Props = { a: 5 };
    const obj2: Required<Props> = { a: 5,b:5 };


    Pick<Type, Keys>

    作用:构建返回一个根据Keys从类型Type拣选所需的属性的新类型

    Keys的类型有要求:string literal or union of string literals

    interface Todo {
      title: string;
      description: string;
      completed: boolean;
    }
     
    type TodoPreview = Pick<Todo, "title" | "completed">;
     
    const todo: TodoPreview = { // 只需要Keys: title and completed
      title: "Clean room",
      completed: false,
    };

    和pick相反的操作是Omit

    Omit<Type, Keys>

    作用:以一个类型为基础支持剔除某些属性,然后返回一个新类型。

    type Person = {
        name: string;
        age: string;
        location: string;
    };
    
    type PersonWithoutLocation = Omit<Person, 'location'>;
    // PersonWithoutLocation equal to QuantumPerson
    type QuantumPerson = {
        name: string;
        age: string;
    };


    联合类型操作:Exclude/Extract、NonNullable

    • Extract:只要取出,從許多項目中挑出能夠符合(extends)特定規則的

    • Exclude:排除後留下,從許多項目中排除符合(extends)特定規則的


    Exclude<Type, ExcludedUnion>

    作用:从Type中排除可以分配给ExcludedUnion的类型

    type T0 = Exclude<"a" | "b" | "c", "a">; // type T0 = "b" | "c"
    type T1 = Exclude<"a" | "b" | "c", "a" | "b">;  // type T1 = "c"
    type T2 = Exclude<string | number | (() => void), Function>; // type T2 = string | number


    18becb1cec4f4d63a8ac836a2f093f7a_tplv-k3u1fbpfcp-zoom-in-crop-mark_3024_0_0_0.webp

    Extract<Type, Union>

    作用:从Type中检出可以分配给Union的类型

    type T0 = Extract<"a" | "b" | "c", "a" | "f">; // type T0 = "a"
    type T1 = Extract<string | number | (() => void), Function>; // type T1 = () => void



    NonNullable<Type>

    作用:排除类型Type中的null、undefined

    type T0 = NonNullable<string | number | undefined>; // type T0 = string | number
    type T1 = NonNullable<string[] | null | undefined>;// type T1 = string[]




    修饰类:Readonly

    Readonly<Type>

    作用:将Type所有属性置为只读

    interface Todo {  title: string; } 
    const todo: Readonly<Todo> = {  title: "Delete inactive users" };

    readonly的含义跟JS的const不能修改的含义一样,指的是不能重写(重写赋值)。

    这个方法对于Object.freeze的定义非常适用:

    function freeze<Type>(obj: Type): Readonly<Type>;

    更多参看:https://jkchao.github.io/typescript-book-chinese/typings/readonly.html


    属性修饰符

    在TS2.8版本之前,支持对映射类型的属性添加readonly、?的修饰符,但是并没有提供移除修饰符的能力。 默认它的修饰符是跟映射类型保持一致的,有兴趣的可以看这个PR以及它fix的issue。那现在映射类型它支持通过+或者-来添加 或 移除readonly或者?修饰符。
    type A = { readonly a? : number, b: string };
    type MockRequired<T> = {
        -readonly [P in keyof T]-?: T[P] // 这里可以不需要-?
    };
    
    const test: MockRequired<A> = { //  我希望a是必须的
        a: 10,
        b: 'b'
    };
    
    test.a = 20; // 我希望可以修改a

    这里推荐阅读:《用了 TS 映射类型,同事直呼内行! https://juejin.cn/post/7089943758543781896



    函数类:InstanceType、ReturnType、ThisType、Parameters、ConstructorParameters


    InstanceType

    作用:获取构造函数类型的实例类型

    class C {
      x = 0;
      y = 0;
    }
    
    type T0 = InstanceType<typeof C>; // C


    ReturnType<T> 

    作用:获取函数 T 的返回类型

    type T0 = ReturnType<() => string>; // string
    type T1 = ReturnType<(s: string) => void>; // void
    type T2 = ReturnType<<T>() => T>; // {}


    ThisType<T> 

    作用:用于指定上下文对象的类型

    interface Person {
        name: string;
        age: number;
    }
    
    const obj: ThisType<Person> = {
      dosth() {
        this.name // string
      }
    }


    Parameters<T> 

    作用:获得函数的参数类型组成的元组类型

    type A = Parameters<() => void>; // []
    type B = Parameters<typeof Array.isArray>; // [any]
    type C = Parameters<typeof parseInt>; // [string, (number | undefined)?]
    type D = Parameters<typeof Math.max>; // number[]


    ConstructorParameters<T> 

    作用:提取构造函数类型的所有参数类型。它会生成具有所有参数类型的元组类型(如果 T 不是函数,则返回的是 never 类型)。

    type A = ConstructorParameters<ErrorConstructor>; // [(string | undefined)?]
    type B = ConstructorParameters<FunctionConstructor>; // string[]
    type C = ConstructorParameters<RegExpConstructor>; // [string, (string | undefined)?]


    操作符类:typeof、keyof、in、infer

    typeof、keyof、in

    其实你就理解为 操作结果 为ts 类型

    interface Person {
      name: string;
      age: number;
    }
    
    const sem: Person = { name: 'semlinker', age: 30 };
    // typeof 操作符可以用来获取一个变量声明或对象的类型。
    type Sem= typeof sem; // -> Person
    // keyof 操作符可以用来一个对象中的所有 key 值:
    type K1 = keyof Person; // "name" 
    // in 用来遍历枚举类型:
    type Keys = "a" | "b" | "c"
    
    type Obj =  {
      [p in Keys]: any
    } // -> { a: any, b: any, c: any }



    参看文章:

    TypeScript学习之Utility Types https://juejin.cn/post/6994038108543156238

    https://pjchender.dev/typescript/ts-unions-intersections/

    用了 TS 条件类型,同事直呼 YYDS! https://juejin.cn/post/7096265620445986823




    转载本站文章《TS数据类型(1):从Utility Types发微,分类学习笔记》,
    请注明出处:https://www.zhoulujun.cn/html/webfront/ECMAScript/typescript/2022_0922_8876.html