How to create a type excluding instance methods from a class in typescript?

后端 未结 3 1423
小蘑菇
小蘑菇 2021-02-05 17:19

Given a class, containing both properties and methods, I\'d like to derive a type that just contains its properties.

For example, if I define a class as follow:

         


        
相关标签:
3条回答
  • 2021-02-05 17:50

    I've found a way to exclude all properties that match a given type, thanks to this article: https://medium.com/dailyjs/typescript-create-a-condition-based-subset-types-9d902cea5b8c

    I made a few adaptations, but here is the details:

    // 1 Transform the type to flag all the undesired keys as 'never'
    type FlagExcludedType<Base, Type> = { [Key in keyof Base]: Base[Key] extends Type ? never : Key };
        
    // 2 Get the keys that are not flagged as 'never'
    type AllowedNames<Base, Type> = FlagExcludedType<Base, Type>[keyof Base];
        
    // 3 Use this with a simple Pick to get the right interface, excluding the undesired type
    type OmitType<Base, Type> = Pick<Base, AllowedNames<Base, Type>>;
        
    // 4 Exclude the Function type to only get properties
    type ConstructorType<T> = OmitType<T, Function>;
    

    Try It

    There might be a simpler way, I've tried playing with ConstructorParameters and defining a constructor signature but without results.

    Update

    Found an equivalent while browsing the typescript documentation here: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#distributive-conditional-types

    type NonFunctionPropertyNames<T> = {
      [K in keyof T]: T[K] extends Function ? never : K;
    }[keyof T];
    type NonFunctionProperties<T> = Pick<T, NonFunctionPropertyNames<T>>;
    

    It's a bit less verbose since the omitted type is not generic, but it's the same idea.

    0 讨论(0)
  • 2021-02-05 17:56

    Given a class, containing both properties and methods, I'd like to derive a type that just contains its properties.

    From your example, it seems like you want the result to contain only fields (as opposed to only properties). Here is a type that picks out the fields from an object or class instance.

    type DataPropertyNames<T> = {
      [K in keyof T]: T[K] extends Function ? never : K;
    }[keyof T];
    
    type DataPropertiesOnly<T> = {
      [P in DataPropertyNames<T>]: T[P] extends object ? DTO<T[P]> : T[P]
    };
    
    export type DTO<T> = DataPropertiesOnly<T>;
    

    I have used the acronym DTO to mean Data Transfer Object. Thank you to l00ser2410656 for this playground demo.

    0 讨论(0)
  • 2021-02-05 18:10

    While reading this issue, I found someone posting this succinct type

    type ExcludeMethods<T> = 
      Pick<T, { [K in keyof T]: T[K] extends (_: any) => any ? never : K }[keyof T]>;
    

    Note that this type does not remove getters and setters.

    0 讨论(0)
提交回复
热议问题