【发布时间】:2021-04-18 14:51:51
【问题描述】:
我在这里查看了这个问题:
最佳答案的 DeepPartial 类型定义如下:
type DeepPartial<T> = {
[P in keyof T]?: DeepPartial<T[P]>;
};
我测试过,这种类型按预期工作,但我不能完全理解它在内部是如何工作的。
让我们以同一个问题的界面为例:
interface Foobar {
foo: number;
bar: {
baz: boolean;
qux: string;
};
}
当P=bar时,很容易理解它会递归进入
DeepPartial<{
baz: boolean;
qux: string;
}>
并使“baz”和“qux”键可选。
但我不明白的是,原始类型的递归是如何工作的?
就像foo 键一样,DeepPartial<number> 与number 有何相同之处?当 T=number 时,
[P in keyof number]?: DeepPartial<number[P]>;
对我来说没有意义。
在我看来,DeepPartial 的实现应该是这样的:
type DeepPartial<T> = {
[P in keyof T]?: isPrimitive(T[P]) ? T[P] : DeepPartial<T[P]>;
};
但原始实现也可以,但我不明白如何。
我希望我能很好地解释我的问题。这是示例游乐场:
编辑: 我进一步调查发现
type DeepPartial<T> = {
[P in keyof T]?: any;
};
type DeepPartialTest<T> = {
[P in keyof number]?: any;
};
现在 DeepPartial<number> 将返回 number 类型,但 DeepPartialTest<number> 不会。这让我觉得更奇怪。
编辑2添加截图:
这按预期工作:
这不是:
什么时候实际上两者应该是一样的??
【问题讨论】:
-
DeepPartial只是使键可选。number是一个原始人,在技术上没有密钥,所以DeepPartial<number>是一个无操作 -
但 DeepPartial
在这种情况下不应该返回空对象 ({}) 类型而不是“数字”类型吗? -
不,不应该。原语在技术上没有方法,当您在其上使用任何方法时,它只是转换为对象。你不能声称有一个数字(例如,
42),但你不能以某种方式做到(42).toString(),因为你不能从原语中删除toString()。它们是不可变的。 -
仍然不明白 DeepPartial
如何返回数字类型。因此,如果我将 DeepPartial 类型定义为没有键的对象(因为 keyof number 没有键),我得到的只是 T 而不是没有键的对象?无法理解逻辑是如何工作的 -
number是原语,而不是对象。基元是不可变的,因此在5和42上具有不同的属性是没有意义的。
标签: typescript