如何将嵌套接口转换为 TypeScript 中的类型别名?

问题描述 投票:0回答:1

我正在尝试将嵌套接口类型(来自我无法更改的第三方库)分配给具有兼容索引签名的类型。

完成此类分配的一种方法是首先将接口转换为类型别名(参考。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
typescript
1个回答
0
投票

类型

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 代码链接

© www.soinside.com 2019 - 2024. All rights reserved.