Есть ли способ "извлечь" тип свойства интерфейса TypeScript?

Предположим, есть файл ввода для библиотеки 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 (которое не работает и приводит к ошибке "Can not find name I2" ). Спасибо заранее.


Изменить: после небольшого воспроизведения в TS Playground я заметил, что следующий код достигает именно того, что я хочу:

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

Однако для этого требуется резервированная переменная x. Я ищу способ добиться этого без этой декларации.

Ответ 1

Это было невозможно, но, к счастью, это сейчас, так как TypeScript версия 2.1. Он был выпущен 7 декабря 2016 года и вводит индексированные типы доступа, также называемые типами поиска.

Синтаксис выглядит точно так же, как доступ к элементу, но написанный вместо типов. Итак, в вашем случае:

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 Игровая площадка.

Ответ 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'