我正在尝试将嵌套接口类型(来自我无法更改的第三方库)分配给具有兼容索引签名的类型。
完成此类分配的一种方法是首先将接口转换为类型别名(参考。https://github.com/Microsoft/TypeScript/issues/15300)。
如何将嵌套接口转换为类型别名?
下面是一个例子(playground)。
interface InnerIObj {
b: string;
}
interface IObj {
x: {
a: string;
} & InnerIObj;
}
type IndexSignature = {
[key: string]:
| IndexSignature
| string
};
declare const obj: IObj;
type TObj = Pick<IObj, keyof IObj>; // Did not work, as the nested interfaces remains interfaces.
const objAlias: TObj = obj;
const error: IndexSignature = objAlias
类型
Pick<T, keyof T>
相当于“身份”映射类型{[K in keyof T]: T[K]}
。 如果您想递归地应用它,您可以定义一个嵌套的“身份”映射类型,例如
type NestedId<T> = { [K in keyof T]: NestedId<T[K]> }
然后将其应用到您的类型:
type TObj = NestedId<IObj>;
/* type TObj = {
x: {
a: string;
b: string;
};
} */
const objAlias: TObj = obj;
const noError: IndexSignature = objAlias; // okay!
这适用于你的例子。我在“身份”周围加上了“吓人引号”,因为存在输出与输入不相等的边缘情况。例如,调用签名未映射,因此函数将失去其功能:
interface IObjWithMethods {
foo(): void;
bar(x: string): void;
baz: {
qux(): void;
}
}
type TObjWithMethods = NestedId<IObjWithMethods>;
/* type TObjWithMethods = {
foo: {};
bar: {};
baz: {
qux: {};
};
} */
如果这对你很重要,你可以使
NestedId<T>
变得更复杂(但你需要决定是否要保留函数不转换,或者转换它们的参数和返回类型,然后你会遇到
generic的问题函数和重载函数,以及😤)。但由于所提出的问题不需要这样做,所以我不会在这里进一步离题。 Playground 代码链接