我正在尝试编写一个nest()
函数,该函数接受2个对象实体和一个键,并将第二个嵌套在提供的键中的第一个中。
实体1
{
"foo": "bar"
}
实体2
{
"few": "baz"
}
实体2嵌套在wow
中的实体1中
{
"foo": "bar",
"wow": {
"few": "baz"
}
}
我带来了以下实现,它的工作原理就像一个魅力
type Nested <
LeftEntity extends Record<string, unknown>,
RightEntity extends Record<string, unknown>,
NestKey extends string
> = LeftEntity & {
[Key in NestKey]: RightEntity
}
const nest = <
LeftEntity extends Record<string, unknown>,
RightEntity extends Record<string, unknown>,
NestKey extends string
> (
leftEntity: LeftEntity,
rightEntity: RightEntity,
nestKey: NestKey
): Nested<LeftEntity, RightEntity, NestKey> => {
const nested = {
...leftEntity,
[nestKey]: rightEntity
} as Nested<LeftEntity, RightEntity, NestKey>
return nested
}
现在我想给nestKey
一个默认值,并将其作为一个可选参数。因此,我天真地尝试:
const nest = <
LeftEntity extends Record<string, unknown>,
RightEntity extends Record<string, unknown>,
NestKey extends string
> (
leftEntity: LeftEntity,
rightEntity: RightEntity,
nestKey: NestKey = 'meta' // <= HERE
): Nested<LeftEntity, RightEntity, NestKey> => {
// ...
}
但编译器抱怨道:
TS2322:无法将类型"string"分配给类型"NestKey"。"string"可以分配给类型约束"NestKey",但"NestKey"可以用约束"string"的不同子类型实例化。
虽然我完全理解为什么会抱怨(我理解,这不是我的问题(;我想知道实现我想要的目标的模式是什么。
我想为解决方案添加一些限制:
- 尽可能避免使用类型转换
- 具有完美的返回类型类型(特别是使用vscode使其自动完成(
这可能吗?
我设法实现了它,泛型类型可以省略,nestKey也可以省略,如果泛型参数被省略或提供为"元";
Playgorund链接
const nest = <
LeftEntity extends Record<string, unknown>,
RightEntity extends Record<string, unknown>,
NestKey extends string = "meta" // default meta
> (
leftEntity: LeftEntity,
rightEntity: RightEntity,
nestKey: NestKey = "meta" as NestKey //default meta
): Nested<LeftEntity, RightEntity, NestKey> => {
const nested = {
...leftEntity,
[nestKey]: rightEntity
} as Nested<LeftEntity, RightEntity, NestKey>
return nested
}
如果你这样尝试,它会抱怨
const a = nest<
{hey: string},
{ho: string}
>(
{hey: 'foo'},
{ho: 'bar'},
"aaa"
)