2016-12-20 25 views
8

Tôi có một chức năng mà xây dựng một đối tượng, như thế này:Xuất kiểu trả về của hàm trong nguyên cảo

function toast() { 
    return { 
    a: "a", 
    b: "b" 
    } 
} 

tôi có thể xác định loại của hàm như

type ToastFunctionType = typeof toast 

loại này sẽ là

() => { a: string; b: string; } 

Tuy nhiên, tôi chỉ muốn loại giá trị trả về. Có thể trích xuất loại giá trị trả về của bánh mì nướng không? Trong trường hợp sử dụng của tôi, các giá trị thực tế của các đối tượng đang sử dụng các đối số kiểu generic khá dài dòng. Loại suy luận được họ chỉ đúng và tôi muốn tránh duy trì một giao diện rất tiết (mà tôi cần phải xuất khẩu).

Những gì tôi muốn trong trường hợp bánh mì nướng chỉ là

{ a: string; b: string; } 

Trả lời

10

Có nó có thể. Bí quyết là có một số giá trị ở đâu đó được khai báo với loại bạn cần (kiểu trả về là toast()), mà không thực sự gọi toast(). Bạn có thể làm điều đó bằng cách giới thiệu một hàm khác trả về một giá trị của kiểu thích hợp (giá trị thực tế là null), sau đó tạo một biến và gán nó giá trị trả về bởi hàm đó, sau đó nhận được typeof.

Tôi không thể tìm cách mà không thêm biến không sử dụng, nhưng vì biến được khởi tạo bởi null ngay lập tức được trả về từ hàm, tôi giả sử rằng thời gian chạy trên không đáng kể. Đây là mã:

function toast() { 
    return { 
    a: "a", 
    b: "b" 
    } 
} 

function getReturnType<R> (f: (...args: any[]) => R): {returnType: R} { 
    return null!; 
} 

// dummy variable, used for retrieving toast return type only 
let toastType = getReturnType(toast); 

export type ToastReturnType = typeof toastType.returnType; 

CẬP NHẬT Feb 2018

Trong phiên bản 2.8 sắp tới, có some new language features mà làm cho nó có thể mà không liên quan đến các biến giả và chức năng.

Ví dụ này biên dịch với nguyên cảo @ tiếp theo:

export function z() { 
    return {a: 1, b: '2'} 
} 

export function v() { 
} 

type ReturnType<T extends (...args: any[]) => any> = 
    T extends (...args: any[]) => infer R ? R : never; 

export type RZ = ReturnType<typeof z>; // { a: number; b: string; } 
export type RV = ReturnType<typeof v>; // void 
+1

lừa gọn gàng! Tôi sẽ không tự mình nghĩ ra điều này. Nó trông hơi hack nhưng nó có lợi cho ứng dụng của chúng tôi bằng cách loại bỏ các khai báo dài với 2 dòng. Đó là một sự xấu hổ mà nó không thể sử dụng một biểu thức sau khi typeof (một cái gì đó giống như typeof (ExtractReturnType (bánh mì nướng)) mà có thể dễ đọc hơn so với khai báo biến theo sau là typeof – user3711864

+1

Điều này sẽ không hoạt động nếu 'strictNullChecks' Có một lỗi hiếm hoi tại 'return null' – Louis

+2

@Louis fixed, thanks, đây là một trong những trường hợp hiếm hoi khi bạn phải sử dụng toán tử khẳng định không null với' null'. – artem

Các vấn đề liên quan