36

Here is the code

class A {
    x = 0;
    y = 0;
    visible = false;
    render() {

    }
}

type RemoveProperties<T> = {
    readonly [P in keyof T]: T[P] extends Function ? T[P] : never//;
};


var a = new A() as RemoveProperties<A>
a.visible // never
a.render() // ok!

I want to remove " visible / x / y " properties via RemoveProperties ,but I can only replace it with never

Wander Wang
  • 391
  • 1
  • 3
  • 5

2 Answers2

66

TS 4.1

You can use as clauses in mapped types to filter out properties in one go:

type Methods<T> = { [P in keyof T as T[P] extends Function ? P : never]: T[P] };
type A_Methods = Methods<A>;  // { render: () => void; }

When the type specified in an as clause resolves to never, no property is generated for that key. Thus, an as clause can be used as a filter [.]

Further info: Announcing TypeScript 4.1 - Key Remapping in Mapped Types

Playground

ford04
  • 66,267
  • 20
  • 199
  • 171
  • 2
    This pattern started [causing issues](https://github.com/microsoft/TypeScript/issues/51141) for me, in TS 4.7+ above. Any idea why? – josias Oct 11 '22 at 08:12
58

You can use the same trick as the Omit type uses:

// We take the keys of P and if T[P] is a Function we type P as P (the string literal type for the key), otherwise we type it as never. 
// Then we index by keyof T, never will be removed from the union of types, leaving just the property keys that were not typed as never
type JustMethodKeys<T> = ({[P in keyof T]: T[P] extends Function ? P : never })[keyof T];  
type JustMethods<T> = Pick<T, JustMethodKeys<T>>; 
Titian Cernicova-Dragomir
  • 230,986
  • 31
  • 415
  • 357
  • I have another question https://stackoverflow.com/questions/49420657/how-to-remove-properties-and-promisify-method-via-mapped-type-in-typescript , thanks for your help – Wander Wang Mar 22 '18 at 04:38