Type Guard Typescript неправильно выводит параметры функции остановки
У меня есть пример Typescript с параметрами типа guard и функцией rest:
interface BaseProps {
username: string;
password: string;
}
type Props = BaseProps & (
| {isAdmin: true, adminName: string}
| {isAdmin: false}
)
// Doesn't works
const myFn = ({isAdmin, ...rest}: Props) => {
if(isAdmin === true) {
rest.adminName; // Property 'adminName' does not exist on type '{ username: string; adminName: string; } | { username: string; }'.
}
}
// It works
const myFn2 = (args: Props) => {
if(args.isAdmin === true) {
args.adminName;
}
}
Что не так с остальными параметрами и охраной типов?
ОБНОВЛЕНИЕ РЕШЕНИЯ:
Я нашел решение, используя
Assert Functions
чтобы решить проблему.
declare function assertType<T>(val: unknown): asserts val is T;
const myFn = ({password, isAdmin, ...rest}: Props) => {
if(isAdmin === true) {
assertType<Omit<Props & {isAdmin: true}, keyof Props>>(rest);
rest.adminName; // <=== HERE
rest.username;
// Should be error
rest.password;
}
}
1 ответ
Тип
Props
является
{имя пользователя: строка, isAdmin: true, adminName: строка} | {имя пользователя: строка, isAdmin: false }
Когда вы утверждаете ценность
isAdmin
на объекте типа
Prop
(например,
if
оператор), машинописный текст может сузить фактический тип между
{ username: string, isAdmin: true, adminName: string }
и
{ username: string, isAdmin: false }
.
Если вы удалите
isAdmin
путем деструктурирования тип
rest
становится
{имя пользователя: строка, adminName: строка} | {имя пользователя: строка}
Ценности
isAdmin
и
rest
стать некоррелированными, и это единственный способ сузить тип
rest
состоит в том, чтобы утверждать наличие
adminName
свойство.
Возможно, вам не стоит использовать параметры отдыха для этого конкретного случая. Вы также можете вручную использовать
rest
переменная внутри
if
.