Функция Typescript возвращает тип, основанный на необязательных аргументах

#typescript

Вопрос:

Как можно устранить плохие типы?

Песочница TS.

 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
 

Комментарии:

1. песочница TS не работает

Ответ №1:

Поэтому вам просто нужно немного скорректировать определение функции, чтобы:

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

Проблема, с которой вы сталкиваетесь, заключается в том, что Action она расширяется "seal" | "preventExtensions" | "freeze" , и поэтому по определению Action extends "freeze" всегда будет верной, поскольку она всегда расширяет это.

Поэтому, чтобы правильно сузить типы, вам нужно сделать "freeze" extends Action то, что будет справедливо только для одной из трех возможностей для действий.

Ссылка на игровую площадку

Надеюсь, в этом есть смысл