Có cách nào để "trích xuất" loại thuộc tính giao diện TypeScript không?


115

Giả sử có một tệp nhập cho thư viện X bao gồm một số giao diện.

interface I1 {
    x: any;
}

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

Để làm việc với thư viện này, tôi cần truyền xung quanh một đối tượng có cùng kiểu với I2.y. Tất nhiên, tôi có thể tạo giao diện giống hệt nhau trong các tệp nguồn của mình:

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

let myVar: MyInterface;

nhưng sau đó tôi có gánh nặng phải cập nhật nó với cái từ thư viện, hơn nữa nó có thể rất lớn và dẫn đến trùng lặp mã rất nhiều.

Do đó, có cách nào để "trích xuất" loại thuộc tính cụ thể này của giao diện? Một cái gì đó tương tự như let myVar: typeof I2.y(không hoạt động và dẫn đến lỗi "Không thể tìm thấy tên I2"). Cảm ơn trước.


Chỉnh sửa : sau khi chơi một chút trong TS Playground, tôi nhận thấy rằng đoạn mã sau đạt được chính xác những gì tôi muốn:

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

Tuy nhiên nó yêu cầu một biến dư thừa xđược khai báo. Tôi đang tìm cách để đạt được điều này mà không cần tuyên bố đó.


1
cái nào không hoạt động - nó biểu hiện như thế nào? Thông báo lỗi thực tế mà bạn thấy là gì?
Bartek Banachewicz,

@BartekBanachewicz đã cập nhật
Kuba Jagoda,

Câu trả lời:


234

Trước đây thì không thể nhưng may mắn là bây giờ đã có, kể từ phiên bản TypeScript 2.1 . Nó đã được phát hành vào ngày 7 tháng 12 năm 2016 và nó giới thiệu các loại truy cập được lập chỉ mục còn được gọi là các loại tra cứu .

Cú pháp trông giống hệt như truy cập phần tử nhưng được viết thay cho các kiểu. Vì vậy, trong trường hợp của bạn:

interface I1 {
    x: any;
}

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

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

Bây giờ myVarcó loại I2.y.

Kiểm tra nó trong TypeScript Playground .


1
Trong trường hợp khi 'y' là một mảng, có cách nào để trích xuất kiểu của các phần tử không? ví dụ: I2 {y: {..} []}
John B

1
@JohnB vâng, bạn có thể làm điều đó theo cách chính xác, vì chỉ số mảng cũng giống như thuộc tính đối tượng. Kiểm tra nó tại đây: stylescriptlang.org/play/…
Kuba Jagoda

1
@JohnB vâng, bạn có thể truy cập nó theo cùng một cách tức là. I2['y'][0]Xem: typescriptlang.org/play/...
Michał Miszczyszyn

2
Đây là khả năng thực sự tuyệt vời
Geradlus_RU 10/09/19

1
Giả sử chúng ta đang lặp qua các khóa của một đối tượng được xác định bằng cách sử dụng I2kiểu. Làm cách nào để tôi lấy loại khóa cụ thể động khi lặp lại. Điều này; let z: typeof x[a];, đâu alà một khóa nhất định dưới dạng một chuỗi, không hoạt động. Nó cho tôi biết rằng atham chiếu đến một giá trị và phải tham chiếu đến một loại. Tôi sẽ đi đâu để tới đó? Nó thậm chí có thể theo bất kỳ cách nào? Cám ơn!
Emil Walser

-1

Một giao diện giống như định nghĩa của một đối tượng. Sau đó, y là một thuộc tính của đối tượng I2 của bạn, thuộc một loại nhất định, trong trường hợp đó là "ẩn danh".

Bạn có thể sử dụng một giao diện khác để xác định y và sau đó sử dụng nó làm loại y của bạn như thế này

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

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

Bạn có thể đặt giao diện của mình trong một tệp và sử dụng giải nén để có thể nhập nó vào các tệp khác trong dự án của mình

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



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

Bạn có thể nhập nó theo cách đó:

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

Mọi thứ đều ổn, nhưng như tôi đã đề cập - giao diện I1 và I2 đến từ một thư viện bên ngoài và được định nghĩa trong tệp d.ts cho thư viện đó. Do đó có giao diện ytype này sẽ là một sự trùng lặp mã và cần được cập nhật liên tục.
Kuba Jagoda,
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.