有没有一种方法可以“提取” TypeScript接口属性的类型?


124

假设有一个库X的键入文件,其中包含一些接口。

interface I1 {
    x: any;
}

interface I2 {
    y: {
        a: I1,
        b: I1,
        c: I1
    }
    z: any
}

为了使用该库,我需要传递与类型完全相同的对象I2.y。我当然可以在源文件中创建相同的界面:

interface MyInterface {
    a: I1,
    b: I1,
    c: I1
}

let myVar: MyInterface;

但是我却要负担使其与库中的库保持最新的负担,而且它可能很大,并导致大量代码重复。

因此,是否有任何方法可以“提取”该接口的特定属性的类型?类似的内容let myVar: typeof I2.y(不起作用,并导致“找不到名称I2”错误)。提前致谢。


编辑:在TS游乐场玩了一点之后,我注意到以下代码完全实现了我想要的功能:

declare var x: I2;
let y: typeof x.y;

但是,它需要x声明一个冗余变量。我正在寻找一种无需声明即可实现这一目标的方法。


1
哪个行不通-如何体现?您看到的实际错误消息是什么?
Bartek Banachewicz '16

@BartekBanachewicz更新
库巴贾戈达

Answers:


250

TypeScript 2.1版开始,以前是不可能的,但现在是幸运的。它已于2016年12月7日发布,引入了索引访问类型,也称为查找类型

该语法看起来与元素访问完全相同,但是代替了类型。因此,在您的情况下:

interface I1 {
    x: any;
}

interface I2 {
    y: {
        a: I1,
        b: I1,
        c: I1
    }
    z: any
}

let myVar: I2['y'];  // indexed access type

现在的myVar类型为I2.y

TypeScript Playground中进行检查。


1
如果'y'是一个数组,是否有任何方法可以提取元素的类型?例如I2 {y:{..} []}
约翰B

1
@JohnB是的,您可以以完全相同的方式来执行此操作,因为数组索引就像对象属性一样。在此处查看:typescriptlang.org/play/…–库巴雅各达
Kuba Jagoda)

3
@JohnB是的,您可以以相同的方式访问它,即。I2['y'][0]请参阅:typescriptlang.org/play/...
米哈尔Miszczyszyn

2
这真是个了不起的功能
Geradlus_RU '19

1
假设我们正在遍历使用I2类型定义的对象的键。循环时如何动态获取特定键的类型。这个; let z: typeof x[a];,其中a某个键为字符串的位置不起作用。它告诉我,它a引用一个值,而必须引用一个类型。我将如何去做呢?有可能吗?谢谢!
埃米尔·沃尔瑟

-2

接口就像对象的定义。则y是您的I2对象的属性,该属性具有某种类型,在这种情况下为“匿名”。

您可以使用另一个接口定义y,然后将其用作y类型,如下所示

interface ytype {
   a: I1;
   b: I1;
   c: I1;
}

interface I2 {
    y: ytype;
    z: any;
}

您可以将界面放入文件中并使用提取,以便可以将其导入项目的其他文件中

export interface ytype {
   a: I1;
   b: I1;
   c: I1;
}



 export interface I2 {
        y: ytype;
        z: any;
    }

您可以这样导入:

   import {I1, I2, ytype} from 'your_file'

一切都很好,但是正如我提到的那样-接口I1和I2来自外部库,并在d.ts文件中为该库定义。因此,具有此ytype接口将是代码重复,并且需要不断更新。
库巴Jagoda
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.