[英]How to extract if condition to function and not break narrowed types in TypeScript
給出以下 if 語句:
interface MyData {
prop1?: number,
prop2?: number,
}
const x: MyData = {
prop1: 1,
prop2: 2,
}
function fun(a: number, b: number) {
console.log(a, b);
}
if (x.prop1 && x.prop2) {
fun(x.prop1, x.prop2);
}
編譯器能夠推斷在 if 主體內部,定義了 x.prop1 並定義了 x.prop2。
我想通過將其提取到函數來命名條件。
function bothPropsDefined(prop1: number | undefined, prop2: number | undefined): boolean {
return !!prop1 && !!prop2;
}
if (bothPropsDefined(x.prop1, x.prop2)) {
fun(x.prop1, x.prop2);
}
但編譯器未能得出結論,在 if 主體中,兩個 props 都已定義。
// Argument of type 'number | undefined' is not assignable to parameter of type 'number'.
Type 'undefined' is not assignable to type 'number'.(2345)
我怎樣才能給編譯器一個提示,如果bothPropsDefined
返回 true,那么 prop1 和 prop2 被定義了?
我試過類型保護:
function bothPropsDefinedGuard(prop1: number | undefined, prop2: number | undefined): prop1 is number {
return !!prop1 && !!prop2;
}
if (bothPropsDefinedGuard(x.prop1, x.prop2)) {
fun(x.prop1, x.prop2);
}
但我只設法為一個屬性添加了警衛。
更新
對於上述問題,我設法寫了:
function bothPropsDefinedGuard2(x: {prop1?: number, prop2?: number}): x is {prop1: number, prop2: number} {
return !!x.prop1 && !!x.prop2;
}
if (bothPropsDefinedGuard2(x) {
fun(x.prop1, x.prop2);
}
但我的真實情況有點困難,因為道具來自多個對象:
interface MyData1 {
prop1?: number,
}
interface MyData2 {
prop2?: number,
}
const x1: MyData1 = {
prop1: 1,
}
const x2: MyData2 = {
prop2: 2,
}
您正在尋找自定義類型的守衛。 這是一個解決方案:
const x: { prop1: number | undefined, prop2: number | undefined } = {
prop1: 1,
prop2: 2,
}
function fun(a: number, b: number) {
console.log(a, b);
}
// Custom type guard
function propDefined(prop: number | undefined): prop is number {
return typeof prop === 'number';
}
// Use
if (propDefined(x.prop1) && propDefined(x.prop2)) {
fun(x.prop1, x.prop2);
}
注意:你不能有一個類型保護來改變兩個參數的類型。 類型保護只能縮小一個參數,例如prop is number
,如圖所示。
我的目標是命名條件,所以@basarat 的回答並不理想。
我結束了
由於人為添加的組合對象,這也不理想,但讓我命名條件:
interface MyData1 {
prop1?: number,
}
interface MyData2 {
prop2?: number,
}
const x1: MyData1 = {
prop1: 1,
}
const x2: MyData2 = {
prop2: 2,
}
const xCombined: MyData = {
prop1: x1.prop1,
prop2: x2.prop2,
}
if (bothPropsDefinedGuard2(xCombined)) {
fun(xCombined.prop1, xCombined.prop2);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.