有什么方法可以改善对象的属性?
declare const a: {
x?: number
};
if (a.x) {
doSomething(a); // how do I refine `a.x` here to `number`?
}
我了解了原因,并且知道可以将a.x
分配给const,但是我想传递整个a
对象并告诉TS a.x
不再可能undefined
答案 0 :(得分:3)
对于通用解决方案,这是对@AlekseyL。的建议的轻微调整:
function has<T extends {}, K extends keyof T>(a: T, k: K): a is T & { [k in K]-?: T[K] } {
return typeof a[k] !== "undefined";
}
declare const a: {
x?: number
};
if (has(a, "x")) {
doSomething(a);
}
Even More Generic™解决方案:
function has<T extends object, K extends keyof T>(
obj: T,
...props: K[]
): obj is T & { [k in K]-?: NonNullable<T[K]> } {
for (const prop in props) {
if (obj[prop] === null || obj[prop] === undefined) return false;
}
return true;
}
答案 1 :(得分:2)
您可以为此使用type guard:
declare const a: {
x?: number
};
if (hasX(a)) {
doSomething(a); // a is of type { x: number } here
}
function hasX(a: { x?: number }): a is { x: number } {
return !!a.x;
}
答案 2 :(得分:2)
最简单的方法是使用Partial
type。它允许您将现有类型映射到相似的类型,并将所有属性标记为可选。
然后,当您调用doSomething
时,告诉打字稿,现在a
可以通过强制转换视为完整项目。
interface Item {
x: number
}
const a: Partial<Item> = {};
if (a.x) {
doSomething(a as Item);
}
function doSomething(item: Item) { /* ... */ }
这将告诉打字稿将“ a
”作为“部分项”来引用。
如果您想避免在最后使用强制转换,并使用打字稿机制来了解a
是完整类型,则可以使用Type Guard。这样,您无需告诉打字稿对待a as Item
。
interface Item {
x: number
}
const a: Partial<Item> = {};
if (isItemComplete(a)) {
doSomething(a);
}
function doSomething(item: Item) { /* ... */ }
function isItemComplete(item: Partial<Item>): item is Item {
return !!item.x; // <-- make sure everything exists on item
}
当我们在isItemComplete
中调用if
时,打字稿知道:在if
范围内,a
绝对是完整的{ {1}},而不是Item
。在该Partial<Item>
之外,打字稿将继续将if
视为a
。