在以下情况下,我不想信任不受信任的对象,并希望在对每个字段进行操作之前先检查每个字段是否为真。但是,使用Partial泛型时,它不会推断在尝试将字段传递给函数时该字段不是未定义的。有更好的方法来解决这个问题吗?
7855
错误:
export interface IFoo {
id: number;
value: string;
}
export function DoBar(obj: IFoo) {
// do stuff
return;
}
const untrustedObj: Partial<IFoo> = { id: 1, value: 'test' };
if (untrustedObj.id && untrustedObj.value) {
DoBar(untrustedObj); // Error
}
答案 0 :(得分:4)
您可以使用is
来写type guard function来缩小对象的类型:
function hasKey<T, K extends keyof T>(obj: Partial<T>, key: K):
obj is Partial<T> & { [k in K]: T[k] }
{
return Object.prototype.hasOwnProperty.call(obj, key);
}
用法:
if(hasKey(untrustedObj, 'id') && hasKey(untrustedObj, 'value')) {
doBar(untrustedObj); // no type error
}
我使用Object.prototype.hasOwnProperty
作为测试此问题的更通用的解决方案,因为您可能想检查布尔属性是否存在(而不是检查其是否为真)。
答案 1 :(得分:2)
请参阅microsoft/TypeScript#28882,了解为什么它不起作用。如果对象不是可区分联合类型,则检查其属性不会缩小对象本身的类型。您可能需要user defined type guard或其他一些重构方法才能完成这项工作。
一种这样的重构是将属性保存到它们自己的变量中,因为如果您检查它们,TypeScript的编译器将缩小变量的类型:
const uId = untrustedObj.id;
const uValue = untrustedObj.value;
if (typeof uId !== "undefined" && typeof uValue !== "undefined") {
DoBar({ id: uId, value: uValue }); // okay
}
我对类型保护功能的建议如下:
function definedProp<T, K extends keyof T>(
obj: T, ...props: K[]
): obj is T & Required<Pick<T, K>> {
return props.every(k => typeof obj[k] !== "undefined");
}
这将检查obj
为props
数组中的每个键定义一个值,如果是,则它将缩小传入的obj
。然后像这样使用它:
if (definedProp(untrustedObj, "id", "value")) {
DoBar(untrustedObj); // okay
}
好的,希望能有所帮助;祝你好运!