【发布时间】:2021-09-08 01:31:59
【问题描述】:
这个问题和我之前做的一个很相似。
我建议先阅读我之前的问题:How to copy the structure of one generic type to another generic in TypeScript?
我希望克隆嵌套对象类型的结构,而不是克隆平面对象类型的结构。
换句话说,我正在寻找一个函数,给定......
// ...this input type
interface NestedInput {
name: string;
arr: [
string,
Date,
{a: boolean}
];
nestedObject: {
x: number;
y: number;
};
}
// ...it produces this output type
type StringMethod = (val: string) => void;
type DateMethod = (val: Date) => void;
type NumMethod = (val: number) => void;
type BoolMethod = (val: boolean) => void;
interface NestedOutput {
name: StringMethod;
arr: [
StringMethod,
DateMethod,
{
a: BoolMethod;
}
];
nestedObject: {
x: NumberMethod;
y: NumberMethod;
}
}
再次强调,它必须是完全类型安全的,这样我才能使用智能感知访问 output.nestedObject.x 或 output.arr[2].a。
过去 2 天我一直在绞尽脑汁想弄清楚这一点,所以任何帮助都将不胜感激!
PS:您可能已经注意到,我们遇到了定义何时遍历嵌套对象的问题。例如,不会遍历 Date 对象,但可能会遍历其他一些结构。为了防止这成为一个问题,你可以假设如果对象是一个普通的 JS 对象(见下面的函数),那么遍历是可以的。
const getClass: (object: any) => string = Function.prototype.call.bind(Object.prototype.toString);
const isVanillaObject = (obj: any) => {
return getClass(obj) === "[object Object]";
}
【问题讨论】:
-
“例如不会遍历 Date 对象”:我的评论与问题没有直接关系,但通常(IMO)集合更适合动态键值对。其他属性与键完全分开,因此您不必担心确定是否要遍历对象,或者要遍历哪些属性。话虽如此,集合并不好用,因为它们没有方括号符号等。
-
您的函数
isVanillaObject是运行时代码,并且(据我所知)在类型系统中不可用。此函数必须转换为等效的模板(我不知道这可能或不可能)
标签: javascript typescript typescript-generics