typescript - 如何使用交集类型默认泛型函数参数
问题描述
我试图弄清楚为什么下面的代码不能像我期望的那样工作。交集类型似乎可以正常工作(在函数内部重新定义时),但是将其用作通用参数类型的默认值则不行。
interface A {
a: string
}
interface B {
b: string
}
interface C {
c: string
}
function returnStuff<T = A & B>(
optionalReturnFn?: (value: T) => T): (value: T) => T {
const defaultReturnFn = (value: T) => {
value.a // <----- why does this a error
return value
}
return optionalReturnFn ? optionalReturnFn : defaultReturnFn
}
function returnStuff2<T extends A & B>(
optionalReturnFn?: (value: T) => T): (value: T) => T {
const defaultReturnFn = (value: T) => {
value.a // <----- while this one does not
return value
}
return optionalReturnFn ? optionalReturnFn : defaultReturnFn
}
const bc: B & C = { b: 'b', c: 'c' } // <--- valid intersection type
// Works as expected when calling fn but DOESN't work as I'd expect internally to fn
returnStuff<B & C>((value) => {
return value
})
// Doesn't work when calling fn but DOES work as expected internally to fn
returnStuff2<B & C>((value) => {
return value
})
如果您想解决这些错误,这里是一个TS Playground 。
更新:我最终添加了一个类型保护并在returnStuff
函数定义中使用它。
...
function isDefaultType<DefaultType>(
record: any,
keys: string[]
): record is DefaultType {
return every(keys, (key) => key in record)
}
function returnStuff<T = A & B>(
optionalReturnFn?: (value: T) => T): (value: T) => T {
const defaultReturnFn = (value: T) => {
if(isDefaultType<T>(value, ['a', 'b']) {
value.a // <----- no longer throws an error
return value
}
}
return optionalReturnFn ? optionalReturnFn : defaultReturnFn
}
解决方案
返回东西
T = A & B
旁边显示错误,value.a
因为您只设置了默认值,但您没有限制T
via的类型extends
,T
仍然可以是任何东西,但如果没有指定,它将是A & B
.
returnStuff<C>(v => v);
- 作品。returnStuff(v => v);
- 也有效。value.a
失败,因为value
可以是任何东西,字符串,未定义等。
正确的方法是T extends A & B = A & B
返回东西2
returnStuff2<B & C>
不起作用,因为T extends A & B
(不是默认值,而是定义的基本类型)需要在anda
的联合中缺少的属性。B
C
推荐阅读
- image - 使用 jQuery 上传前预览图像
- kotlin - Kotlin - 检查参数是否为空的通用方法
- mysql - 在 laravel 中显示带有 where not in 子句的值
- javascript - 在 html 画布中单击时停止动画播放
- python - 将俄语文本翻译成我可以放在 python 链接中的文本
- javascript - 将 JSON 数据绑定到 HTML 元素
- powershell - 如何通过 PowerShell 创建 Azure DevOps 服务连接端点
- spring-boot - 使用 springboot 应用程序在 oracle 云存储上上传时,zip/image 文件上传损坏
- javascript - 如何在 Typescript 中缩短这个条件?
- r - 您如何将 st_interpolate_aw 与合法包含点和线交叉点的多边形图层一起使用?