有人可以向我解释一下为什么在这种情况下:
const dataValues: ValueRange[] = res.data.valueRanges.filter((range: ValueRange) => range.values);
const formattedValues: Array<SheetData | undefined> = dataValues.map(this.formatSheetRanges);
const sheetData: Array<SheetData> = formattedValues.filter((sheetData: SheetData | undefined) => sheetDataGuard(sheetData));
function sheetDataGuard(data: SheetData | undefined): data is SheetData {
return !!(<SheetData>data).user;
}
Run Code Online (Sandbox Code Playgroud)
sheetData 数组仍然会抱怨它的类型是
Array<SheetData | undefined>
Run Code Online (Sandbox Code Playgroud)
但如果我将最后一个过滤更改为:
const sheetData: Array<SheetData> = formattedValues.filter(sheetDataGuard);
Run Code Online (Sandbox Code Playgroud)
打字稿不再抱怨了吗?
Array<T>.filter()
这是因为标准 TypeScript 库中方法的类型有一个重载签名,如果已知回调函数是用户定义的类型保护函数,该签名会专门缩小返回的数组元素类型:
interface Array<T> {
filter<S extends T>(
callbackfn: (value: T, index: number, array: T[]) => value is S,
thisArg?: any
): S[];
}
Run Code Online (Sandbox Code Playgroud)
由于 的类型sheetDataGuard
可分配给(value: SheetData | undefined, index: number, array: Array<SheetData | undefined>) => value is SheetData
,因此调用filter
withArray<SheetData | undefined>
作为sheetDataGuard
参数将导致编译器使用推断的 forcallbackfn
选择该重载。SheetData
S
但是,当您使用 with 调用(sheetData: SheetData | undefined) => sheetDataGuard(sheetData)
它时,该函数的类型会被推断为仅返回boolean
。这是因为用户定义的类型保护函数不会传播,也不会为您推断。一旦您开始使用类似的类型,编译器x is Y
通常会对其进行扩展。boolean
您可以使用箭头函数返回类型注释告诉编译器您的箭头函数回调也是类型保护,如下所示:
const sheetData: Array<SheetData> = formattedValues.filter(
(sheetData: SheetData | undefined): sheetData is SheetData =>
sheetDataGuard(sheetData)
);
Run Code Online (Sandbox Code Playgroud)
编译器应该很高兴。当然,如果您打算这样做,您最好忘记定义sheetDataGuard
为单独的函数:
const sheetData: Array<SheetData> = formattedValues.filter(
(sheetData: SheetData | undefined): sheetData is SheetData =>
!!sheetData
);
Run Code Online (Sandbox Code Playgroud)
无论如何,希望有帮助。祝你好运!
归档时间: |
|
查看次数: |
765 次 |
最近记录: |