TypeScript: check that the required properties of

2019-02-27 09:30发布

This doesn't compile (playground):

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

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

Is there a more elegant workaround than params as any?

2条回答
地球回转人心会变
2楼-- · 2019-02-27 10:21

The problem is that the type guard impacts just the type of the field (params.b will have the undefined removed) not the type of whole object (param will continue to have the type { a: Date, b?: Date })

Not sure I would call it more elegant, but we can create a type guard that removes the undefined from a type field:

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);
    }
}

We could even create a version that takes any number of keys:

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);
    }
}
查看更多
对你真心纯属浪费
3楼-- · 2019-02-27 10:29

the error message said property 'b' is optional in type '{ a: Date; b?: Date; }' but required in type '{ a: Date; b: Date; }'

It can be solve like this

myFunctionInternal(params as {a,b}); 

or

myFunctionInternal({a:params.a ,b:params.b});
查看更多
登录 后发表回答