在具有泛型的对象中键入单个属性



给定以下类型:

type A = {
name: 'a';
id: string;
};
type B = {
name: 'b';
url: string;
};
type C = {
name: 'c';
id: string;
};

我想手动创建一个对象,看起来像这样:

{
a: {
pk: 'id'
},
b: {
pk: 'url'
},
c: {
pk: 'id'
}
}

但是我希望它能自动知道允许的顶级属性名("name")每个类型的值)以及pk的可能值(基本上是该类型中的任何属性名称,而不是"名称";是可以接受的)。

我可以为一个类型这样做:

type ABC = A | B | C;
type MyObject<T extends ABC> = {
[Key in T['name']]: {
pk: keyof Omit<T, 'name'>;
};
};
const x: MyObject<A> = {
a: {
pk: 'id',
},
};

该类型将接受ABC类型中的任何一个。但是我不知道如何使对象可以包含所有的ABC类型。

我想要的是输入"a",然后当我去输入它的"pk"值,它知道唯一的潜在值是&;id&;。然后加上"b"钥匙指向同一个对象,它知道唯一可能的"pk"取值为"url"

这些只是示例类型,真正的类型有更多的字段和更多的类型。

我会利用映射类型中的键重映射来遍历输入联合的每个成员,如下所示:

type MyObject<T extends { name: string }> = {
[U in T as U['name']]: { pk: Exclude<keyof U, "name"> }
};

对于A | B | C,求值为:

type M = MyObject<A | B | C>;
/* type M = {
a: {
pk: "id";
};
b: {
pk: "url";
};
c: {
pk: "id";
};
} */

Playground链接到代码

最新更新