如何在TypeScript中将一个泛型类型(嵌套对象)的结构复制到另一个泛型



这个问题与我之前提出的问题非常相似。

我建议先阅读我之前的问题:如何在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;
}
}

同样,它必须是完全类型安全的,这样我就可以使用intellisense访问output.nestedObject.xoutput.arr[2].a

在过去的两天里,我一直在绞尽脑汁想办法弄清楚这一点,所以任何帮助都将不胜感激!


PS:您可能已经注意到,当我们遍历嵌套对象时,会遇到定义问题。例如,不会遍历Date对象,但可能会遍历其他结构。为了防止这成为一个问题,您可以假设,如果对象是一个普通的JS对象(请参阅下面的函数(,那么可以遍历。

const getClass: (object: any) => string = Function.prototype.call.bind(Object.prototype.toString);
const isVanillaObject = (obj: any) => {
return getClass(obj) === "[object Object]";
}

您可以使用extends来打开类型,一个用于对象情况的映射类型,并使用递归来允许深度嵌套:

interface NestedInput {
name: string;
arr: [string, Date, { a: boolean }];
nestedObject: {
x: number;
y: number;
};
}
type StringMethod = (val: string) => void;
type DateMethod = (val: Date) => void;
type NumMethod = (val: number) => void;
type BoolMethod = (val: boolean) => void;
type Methodify<T> = T extends string
? StringMethod
: T extends Date
? DateMethod
: T extends number
? NumMethod
: T extends boolean
? BoolMethod
: {
[K in keyof T]: Methodify<T[K]>;
};
type Output = Methodify<NestedInput>;
//Results in:
type Output = {
name: StringMethod;
arr: [StringMethod, DateMethod, {
a: BoolMethod;
}];
nestedObject: {
x: NumMethod;
y: NumMethod;
};
}

最新更新