如何移除TypeScript类型转换中的unknown类型?
解决方案
首先要明确:你用了async回调的map,得到的是Array<Promise<ProviderRelationshipClaims | undefined>>,直接在后面加filter是对Promise对象做判断(Promise永远是真值),根本没过滤掉resolve后的undefined——这是核心问题。先修正这个,再处理类型收窄。
步骤1:先解析Promise数组
先通过await Promise.all()解析所有Promise,拿到实际的结果数组:
const mappedClaims = await Promise.all( completedProvidersWithoutStripeAccount.map(async (p) => { const provider = await getProviderOrThrow(p.tin); const isPreviouslyApproved = previouslyApproved.includes(provider.status); if (isPreviouslyApproved) return; return toProviderRelationshipClaims({ tin: p.tin, role: ProviderUserSubRoles.ky, status: 'KYCInDraft' }); }) );
步骤2:优雅过滤并收窄类型
此时mappedClaims的类型是Array<ProviderRelationshipClaims | undefined>,以下几种方式都能让TypeScript自动识别过滤后的类型,无需强制类型断言:
方式1:使用类型守卫函数
定义一个通用的类型守卫,明确判断值不是undefined:
function isDefined<T>(value: T | undefined): value is T { return value !== undefined; } const incompleteKYCClaims = mappedClaims.filter(isDefined);
此时incompleteKYCClaims的类型会自动推断为Array<ProviderRelationshipClaims>。
方式2:内联类型谓词
如果不想单独定义函数,可以在filter里直接写类型谓词,告诉TypeScript过滤后的类型:
const incompleteKYCClaims = mappedClaims.filter( (claim): claim is ProviderRelationshipClaims => !!claim );
方式3:用flatMap合并映射与过滤
如果想把映射和过滤合并成一步,可利用flatMap会自动扁平化空数组的特性:
const incompleteKYCClaims = await Promise.all( completedProvidersWithoutStripeAccount.flatMap(async (p) => { const provider = await getProviderOrThrow(p.tin); const isPreviouslyApproved = previouslyApproved.includes(provider.status); if (isPreviouslyApproved) return []; return [toProviderRelationshipClaims({ tin: p.tin, role: ProviderUserSubRoles.ky, status: 'KYCInDraft' })]; }) );
最终完整优化示例(推荐类型守卫写法)
function isDefined<T>(value: T | undefined): value is T { return value !== undefined; } const incompleteKYCClaims = await Promise.all( completedProvidersWithoutStripeAccount.map(async (p) => { const provider = await getProviderOrThrow(p.tin); const isPreviouslyApproved = previouslyApproved.includes(provider.status); if (isPreviouslyApproved) return; return toProviderRelationshipClaims({ tin: p.tin, role: ProviderUserSubRoles.ky, status: 'KYCInDraft' }); }) ).then(mapped => mapped.filter(isDefined));
内容的提问来源于stack exchange,提问作者Igor Shmukler
相关产品推荐
相关产品推荐

