请问typescript如何给泛型的参数指定默认值?
例如
const arrToObj = <T extends Record<L | V, unknown>, L extends string, V extends string>(arr: T[], label:L = 'label' , value:V = 'value'): Record<string, T[L]>
提示如下错误
不能将类型“string”分配给类型“L”。
"string" 可赋给 "L" 类型的约束,但可以使用约束 "string" 的其他子类型实例化 "L"。ts(2322)
回答:
string
类型其实是个类型集合.
在 TS 中,有一种类型是使用一个具体的字符串来表示的,也就是字面量类型(Literal Types).
比如 type A = 'a'
,这里 A
就表示是一个字符串为 'a'
的类型,而不能是别的字符串.
这样的字符串有无数个,对应的这样的字面量类型有无数个,而 string
就是这些所有字符串字面量类型的集合.
当指定 L extends string
时,L
有可能是 label
,也有可能不是,一切都是未知的.
这里会报错断原因,就是因为 L
需要在使用时去指定或者推断出来的,并不一定是 lable
,所以不能在不知道 L
具体的类型时就去指定它实际的值.
除了字符串字面量类型,每个基础类型都有对应的字面量类型,详细可以点击后面的参考链接,去阅读文档.
如果只是想要消除报错的话,可以直接用 as 断言成对应的类型.如下:
const arrToObj = < T extends Record<L | V, unknown>,
L extends string,
V extends string,
>(
arr: T[],
label: L = 'label' as L,
value: V = 'value' as V,
): Record<string, T[L]> => {
return arr as any
}
不过这样会有一个问题,就是当使用默认值是,返回值里的 T[L]
不会被正确推断出来.
这个函数其实可以分为三种情况来看
- 没有默认值,传入三个参数
- value 有默认值,传入两个参数
- label 和 value 有默认值,传入一个参数
这时候使用函数重载来实现最合适了.在使用时也能正确推断出 T[L]
类型了.如下:
function arrToObj< T extends Record<L | V, unknown>,
L extends string,
V extends string,
>(arr: T[], label: L, value: V): Record<string, T[L]>
function arrToObj<T extends Record<L | 'value', unknown>, L extends string>(
arr: T[],
label: L,
): Record<string, T[L | 'value']>
function arrToObj<T extends Record<'label' | 'value', unknown>>(
arr: T[],
): Record<string, T['label' | 'value']>
function arrToObj(
arr: Record<string, unknown>[],
label = 'label',
value = 'value',
) {
return arr as any
}
TS Playground
- Function Overloads
- Literal Types
以上是 请问typescript如何给泛型的参数指定默认值? 的全部内容, 来源链接: utcz.com/p/935911.html