打字稿,更改嵌套在界面中的所有匹配键的类型
Posted
技术标签:
【中文标题】打字稿,更改嵌套在界面中的所有匹配键的类型【英文标题】:Typescript, change types of all matching keys nested in interface 【发布时间】:2021-07-17 07:45:50 【问题描述】:是否可以更改嵌套接口中所有匹配键的类型?
我尝试了几种不同的方法,但都没有成功。我试图保持我的类型的通用签名,如我的示例中所述。我想指定要更改的键/键(“Target”)以及应该是什么类型(“NewType”)。我只想识别键来改变它们的类型。
请参考下面我的界面及其预期结果。我转换界面的方法如下。
似乎第二种方法应该可行,但我不知道如何在递归结束后有条件地检查接口的叶键值(参见第二个示例中的条件)。
Here's a sandbox link as well.
任何帮助将不胜感激。谢谢!
// interface
interface og
a: number,
b: number,
c:
a: number,
b: number,
characters:
woman: string,
man: string,
elf: [boolean, string, number]
more:
elf: boolean
,
,
elf: boolean,
;
// desired transform result (I know "dobby" isn't a typical type)
type og_transformed =
a: number,
b: number,
c:
a: number,
b: number,
characters:
woman: string,
man: string,
elf: ["dobby", "dobby", "dobby"]
more:
elf: "dobby"
,
,
elf: "dobby",
;
// this result could be accepted as well
type og_transformed =
a: number,
b: number,
c:
a: number,
b: number,
characters:
woman: string,
man: string,
elf: "dobby" // <- this is different
more:
elf: "dobby"
,
,
elf: "dobby",
;
方法 1:
// transforming type
type ChangeTypeOfKeys_1<Obj, Target, NewType> =
[K in keyof Obj]: K extends Target
? NewType
: Obj[K]
// type call
type dobby_1 = ChangeTypeOfKeys_1<og, 'elf', 'dobby'>
// result
type dobby_1 =
a: number;
b: number;
c:
a: number;
b: number;
characters:
woman: string;
man: string;
elf: [boolean, string, number];
more:
elf: boolean;
;
;
;
elf: "dobby";
方法 2:
// transforming type
type ChangeTypeOfKeys_2<Obj, Target, NewType> = Obj extends object
?
[K in keyof Obj]: ChangeTypeOfKeys_2<Obj[K], Target, NewType>
: NewType // <- how do I check the key's value in this conditional ???
// type call
type dobby_2 = ChangeTypeOfKeys_2<og, 'elf', 'dobby'>
// result
type dobby_2 =
a: "dobby";
b: "dobby";
c:
a: "dobby";
b: "dobby";
characters:
woman: "dobby";
man: "dobby";
elf: ["dobby", "dobby", "dobby"];
more:
elf: "dobby";
;
;
;
elf: "dobby";
解决方案(来自下面的 Alex):
这里主要是为了在下面的 cmets 中显示 on hover 参考,并避免任何人忽视如此简单的事情,例如我自己...
我还添加了一个解决方案沙箱,其中包含扩展类型和每个功能的描述。为了清晰起见,示例界面已被修改。
Solution sandbox
// transforming type
type ChangeTypeOfKeys_3<Obj, Target, NewType> =
[K in keyof Obj]: K extends Target
? NewType
: Obj[K] extends object
? ChangeTypeOfKeys_3<Obj[K], Target, NewType>
: Obj[K]
// type call
type dobby_3 = ChangeTypeOfKeys_3<og, 'elf', 'dobby'>
// result (on hover)
type dobby_3 =
a: number;
b: number;
c: ChangeTypeOfKeys_3<
a: number;
b: number;
characters:
woman: string;
man: string;
elf: [boolean, string, number];
more:
elf: boolean;
;
;
, "elf", "dobby">;
elf: "dobby";
【问题讨论】:
【参考方案1】:您肯定需要它是递归的以深入嵌套对象。但实际上你需要做两个条件测试:
-
这是应该更换的钥匙吗?您已经在这样做了。
这个值是一个需要递归的对象吗?如果是,则递归,否则我们只返回其类型不变。
你的两次尝试各做一半。您需要将它们组合成一个嵌套的条件类型来执行这两项检查。
type ChangeTypeOfKeys<Obj, Target, NewType> =
[K in keyof Obj]:
// does this value have the target key? If so replace it.
K extends Target ? NewType
// Else, is this value an object? If so, recursively change call ChangeTypeOfKeys
: Obj[K] extends object ? ChangeTypeOfKeys<Obj[K], Target, NewType>
// Else, use the type of this leaf without modification.
: Obj[K]
type OgTransformed = ChangeTypeOfKeys<Og, 'elf', 'dobby'>
declare const elfed: OgTransformed
const elfName = elfed.c.characters.elf // type: 'dobby'
const elfMore = elfed.c.characters.more.elf // type: 'dobby'
Playground
【讨论】:
啊。非常感谢您的简洁答复。效果很好。 从您的回答中,我意识到我实际上在其他迭代中正确设置了变压器类型。不幸的是,我没有意识到 on hover TS 不会一直显示类型。它只是显示变压器类型的下一个递归。我不知道您实际上必须像在答案末尾那样以声明方式访问类型。直到。 我已将我所说的on hover 包含在我的原始帖子中,供任何可能阅读此内容的人使用。 是的,类型脚本并不总是完全处理工具提示中的类型。请注意内部类型是如何包装在ChangeTypeOfKeys< ... >
中的,这表明正在转换的输入类型和进行转换的类型别名。从它的嵌套值中获取真实类型需要深入研究。以上是关于打字稿,更改嵌套在界面中的所有匹配键的类型的主要内容,如果未能解决你的问题,请参考以下文章