Home > Blockchain >  Typescript function return type based on optional arguments
Typescript function return type based on optional arguments

Time:10-19

How can bad types be resolved?

TS sandbox.

interface X<T> {
    abc:T
}

declare function deepLock<Obj extends Record<string, any>,>(obj: Obj): X<Obj>;
declare function deepLock<Obj extends Record<string, any>,>(obj: Obj, options: {}): X<Obj>;
declare function deepLock<
  Obj extends Record<string, any>,
  Action extends "freeze" | "seal" | "preventExtensions",
  Options extends { action?: Action }
>(obj: Obj, options?: Options): Action extends 'freeze' ? X<Obj> : Obj

// ok
const x = deepLock({}) // expect X<{}>
const x2 = deepLock({}, {}) // expect X<{}>

// need to be fixed
const x3 = deepLock({}, {action: 'freeze'}) // expect X<{}>
const x4 = deepLock({}, {action: 'seal'}) // expect Obj
const x5 = deepLock({}, {action: 'preventExtensions'}) // expect Obj

CodePudding user response:

So you just need to adjust your function definition very slightly to:

declare function deepLock<
  Obj extends Record<string, any>,
  Action extends "seal" | "preventExtensions" | "freeze",
>(obj: Obj, options?: { action?: Action }): 'freeze' extends Action ? X<Obj> : Obj;

The problem you are facing is that Action is extending "seal" | "preventExtensions" | "freeze" and so by definition Action extends "freeze" will always be true as it always extends that.

So in order to correctly narrow the types you have to do "freeze" extends Action which will only ever be true for one of the three possibilities for Action.

Playground link

Hope that makes sense

  • Related