打字稿 - 如何使用嵌套映射类型

And*_*Ooi 5 typescript

我得到了一个无法修改的大型复杂接口 X,我想根据我想用作函数参数类型的接口 X 中的属性和子属性定义一些较小的类型。我还想避免单独重新声明 X 中已经存在的内容。

interface X {
  a:number;
  c:{
    aa:number;
    cc:{
      aaa:string;
    }
  },
  d?:{
    aa:number;
    cc:{
      aaa:string;
    }
  },
  e:{
    aa:number;
    cc:{
      aaa:string;
    }
  }[]
}
Run Code Online (Sandbox Code Playgroud)

我知道我可以使用映射类型来访问子类型 [编辑注意:子类型是错误的术语,这应该称为嵌套级别类型,请参阅下面的答案] 这应该是对象的,例如:

type C = X["c"]; // { aa:number; cc:{ aaa:string } } 

type C_CC = X["c"]["cc"]; // { aaa: string }

type D = X["d"]; // { aa:number; cc:{ aaa:string } } | undefined

Run Code Online (Sandbox Code Playgroud)

但是,当属性可能未定义时,事情就变得有点麻烦了。如果我想获得 Xdcc 的类型...(应该给 {aaa:string} )我该怎么做?或者甚至有可能吗?

以下两次尝试给出错误:

type D_CC1 = X["d"]["cc"];  // error? Due to the (d?) possibly undefined?
type D_CC2 = Required<X["d"]>["cc"];  // error also?
Run Code Online (Sandbox Code Playgroud)

另外,当涉及到数组时,我也有点困惑,例如上面的 E:

type E = X["e"]; // { aa:number; cc:{ aaa:string } }[]
type E_CC1 = X["e"]["cc"]; // error
type E_CC2 = X["e"][0]["cc"]; // got the result I wanted: { aaa: string }
Run Code Online (Sandbox Code Playgroud)

第三行似乎有效,但我不确定使用 [0] 的逻辑是什么——似乎很糟糕。我想知道这是否是正确的方法。

编辑:将类型名称从 D_CC 更改为 D_CC1 和 D_CC2 以避免歧义。

jpe*_*erl 8

只是一个细节,但为了不混淆术语,界面中的不是子类型,而是嵌套级别类型。嵌套级别类型具有顶级类型。子类型是您可以在任何需要具有该子类型的类型的地方使用的类型。

接下来,您所说的映射类型实际上就是我们所说的键入运算符。这是一种查找形状中属性类型的方法。

映射类型用于映射对象的键和值类型,如下所示:

type MyMappedType = {
  [Key in K]: ValueType
}
Run Code Online (Sandbox Code Playgroud)

这也是您可以利用 keyof 运算符的地方。Key in keyof Something

Partial<Object>例如,要使形状中的所有字段都可选(为此调用了内置映射类型),您可以使用mapped types

type ShapeAllOptional = {
  [K in keyof MyShape]?: MyShape[K]
}
Run Code Online (Sandbox Code Playgroud)

现在回答你的问题。

type D_CC1 = X["d"]["cc"];  // error? Due to the (d?) possibly undefined?
Run Code Online (Sandbox Code Playgroud)

你可以使用这样的东西

type myStype = NonNullable<X['d']>['cc']
Run Code Online (Sandbox Code Playgroud)

至于使用

type E_CC1 = X["e"]["cc"]; // error
type E_CC2 = X["e"][0]["cc"]; // got the result I wanted: { aaa: string }
Run Code Online (Sandbox Code Playgroud)

是的,它是一个数组,每个项目都具有该形状。我不知道这是否很hacky,但我确实看到过一些看起来有点“干净”的东西。

type E_CC2 = X["e"][number]["cc"];
Run Code Online (Sandbox Code Playgroud)

据我所知,没有更好的方法了。

啊,我差点忘了。

type D_CC2 = Required<X["d"]>["cc"];  // error also?
Run Code Online (Sandbox Code Playgroud)

小心,你在这里所说的是使 X['d'] 中的所有属性成为必需的,即aacc,它们......已经是必需的。Required<X>我认为会实现你想要的吗?