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

Это не компилируется ( детская площадка):

function myFunction(params: {
    a: Date,
    b?: Date
}) {
    if (params.b) {
        myFunctionInternal(params); // ERROR!
    }
}

function myFunctionInternal(params: {
    a: Date,
    b: Date
}) {}

Есть ли более элегантный обходной путь, чем params as any?

2 ответа

Решение

Проблема в том, что защита типа влияет только на тип поля (params.b будет иметь undefined удалены) не тип целого объекта (param будет продолжать иметь тип { a: Date, b?: Date })

Не уверен, что я бы назвал это более элегантным, но мы можем создать защиту типа, которая удаляет неопределенное из поля типа:

type RemoveOptionalFromField<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>> & { [P in K]-?: T[P] }

function notNull<T, K extends keyof T>(o: T | RemoveOptionalFromField<T, K>, key: K) : o is RemoveOptionalFromField<T, K> {
    return !!o[key];
}

function myFunction(params: {
    a: Date,
    b?: Date
}) {
    if (notNull(params, 'b')) {
        params.b.getDate()
        myFunctionInternal(params);
    }
}

Мы могли бы даже создать версию, которая принимает любое количество ключей:

function allNotNull<T, K extends keyof T>(o: T | RemoveOptionalFromField<T, K>, ...keys: K[]) : o is RemoveOptionalFromField<T, K> {
    return keys.every(k => !!o[k]);
}
function myFunction(params: {
    a?: Date,
    b?: Date
}) {
    if (allNotNull(params, 'b', 'a')) {
        params.b.getDate()
        myFunctionInternal(params);
    }
}

Сообщение об ошибке говорит, что свойство 'b' является необязательным в типе '{ a: Date; б?: Дата; }'но требуется в типе' {a: Date; б: дата; }"

Можно решить вот так

myFunctionInternal(params as {a,b}); 

или же

myFunctionInternal({a:params.a ,b:params.b});
Другие вопросы по тегам