Dakito
Dakito

Reputation: 387

Exclude used method

Can we exclude method from type when we use it in fluent api. For example: We have setup class which has step by step methods.

class Setup{
step1(){ return this;}
step2(){ return this;}
step3(){ return this;}
}
let setup = new Setup();

And now what i want achieve. First what i will use will be obviously step1 so: setup.step1(). //And after a dot i still can choose a step1 again but i want to prevent it, as I said before how can i exclude step1 to keep only step2 and step3

Upvotes: 0

Views: 117

Answers (2)

Przemyslaw Jan Beigert
Przemyslaw Jan Beigert

Reputation: 2486

I think I'm close. First let's define Omit util export type Omit<A extends object, K extends string> = Pick<A, Exclude<keyof A, K>> it will create new interface without one specific field.

then let's change type definition of step1 method from step1(): Setup to step1(): Omit<Setup, 'step1'>.

In that case setup1 will return Setup instance without one filed: step1.

Unfortunately you still be able to do this:

setup.step1();
setup.step1();

but when you chain methods, you will received error

setup
    .step1()
    .step1(); // ERROR

because Property 'step1' does not exist on type Omit

Playground [Edited]

Upvotes: 0

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

Reputation: 249716

You can use Omit to exclude the methods. The trick is to get the omitted methods to flow through the calls. Polymorphic this is not an option since it is determined when the class is created (not based on the actual call target). We can use a type parameter to infer this based on the call target (this has to be done so since the call target may already have methods excluded)

type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>
class Setup {
    step1<T extends Partial<Setup>>(this: T) : Omit<T, 'step1'> { return this; }
    step2<T extends Partial<Setup>>(this: T) : Omit<T, 'step2'> { return this; }
    step3<T extends Partial<Setup>>(this: T) : Omit<T, 'step3'> { return this; }
}
let setup = new Setup();

setup.step1().step2().step3()
setup.step1().step2().step2() //err

Also since this might now not contain all methods, we say that T will extends Partial<Setup>. This makes the types workout but it will make this hard to use inside the function so consider using something like const self = this as Setup and using self

Upvotes: 3

Related Questions